mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-28 04:01:10 -04:00 
			
		
		
		
	Compare commits
	
		
			471 Commits
		
	
	
		
			2.1.0
			...
			csfixer-te
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 90bb90cd99 | |||
| ebad76c8d7 | |||
| c35b00493c | |||
| e5ae937a88 | |||
| 736df5fcae | |||
| 89c264c6a9 | |||
| 1837bf3f3e | |||
| 83234cfac3 | |||
| 5ccc9eba4c | |||
| 3f0008ec95 | |||
| 9e98a96d61 | |||
| 27bc89bf76 | |||
| e4c2b44da5 | |||
| 633cad9b89 | |||
| f5bbe68a4b | |||
| 1fac9c9dde | |||
| 1208d3a924 | |||
| 3257b18d58 | |||
| 16a941f787 | |||
| 4f5cd9fba1 | |||
| 80e6a3c757 | |||
| d4e7420640 | |||
| ac30ba599b | |||
| 6dd0ccce8b | |||
| 2f32ff4d5b | |||
| 54a5ca83f8 | |||
| eede2fc17f | |||
| e586adde26 | |||
| 1ffb1b2eec | |||
| 55d838371a | |||
| cdaa1ff103 | |||
| 63f7cdec82 | |||
| fadba7fa3a | |||
| d0f6e207ee | |||
| 845f01f170 | |||
| 7f9938c80d | |||
| 16e4212300 | |||
| 109de237b1 | |||
| 82cf63f200 | |||
| 03fc0fd659 | |||
| c3d3e5e35f | |||
| 909e4f93e4 | |||
| bfd9850bf6 | |||
| 3f7db2793f | |||
| 8693672b09 | |||
| a9b0d62cd6 | |||
| 9f57a4200f | |||
| 9e130b3db8 | |||
| 7c9a846090 | |||
| b2e08dda7f | |||
| a2026fbc8b | |||
| db1b0db461 | |||
| 17c00c322d | |||
| 331b8ea44e | |||
| 428be640c3 | |||
| 51f79433b9 | |||
| 8008ed0527 | |||
| 57b302666a | |||
| ee1d1ccff4 | |||
| 81e7109ad1 | |||
| 784bf39df5 | |||
| f66755c4aa | |||
| b4e1e99d37 | |||
| d8aa3dc8a6 | |||
| 9af51660cb | |||
| 38d0da9618 | |||
| 761c0143ec | |||
| fdc4de5093 | |||
| f8591f96a9 | |||
| e47cb01ce2 | |||
| 454ad3091a | |||
| cc73a8a842 | |||
| cea8405ace | |||
| 49a6e03e9d | |||
| f9d6e8b0cc | |||
| 2b78aacc83 | |||
| 1932c5a75e | |||
| 449968ae88 | |||
| 02a2db4417 | |||
| a53582f916 | |||
| 340bf3be06 | |||
| 7f0da9dc36 | |||
| c4ace76275 | |||
| 553bcc053b | |||
| 375a59a504 | |||
| cfc0a1ef75 | |||
| 392f6f469b | |||
| 6cb8d30915 | |||
| 9b55e84724 | |||
| cf5da7684b | |||
| f47029ca78 | |||
| 761df2ffac | |||
| 8fbc257b23 | |||
| baebfedf37 | |||
| 9321eb9d86 | |||
| 70bed01e7b | |||
| 739efcce79 | |||
| 3695e7d075 | |||
| 8f2033f621 | |||
| 7b95ccb5fc | |||
| b7370ed85c | |||
| 818f2fbaf7 | |||
| 91a1dbf91c | |||
| a4d556f41e | |||
| 83de1c47ee | |||
| 678ace744a | |||
| 9e26fee1b0 | |||
| e455c3de50 | |||
| c4db50d3f0 | |||
| 411ee57946 | |||
| 9c5e9e56f5 | |||
| 8eeafd3fed | |||
| ed978d0174 | |||
| 607b1795bb | |||
| a6c3c815b5 | |||
| ead0ebb012 | |||
| d4550e62f8 | |||
| ff3846137e | |||
| b55f8e5391 | |||
| 0f1d7627ea | |||
| 1be462ef82 | |||
| 8b04e94446 | |||
| fa512629d9 | |||
| 0f99be6cf1 | |||
| fae3af2592 | |||
| d1e70c8989 | |||
| 63094e8112 | |||
| 1b46bddf56 | |||
| 422bf74600 | |||
| d003e61d41 | |||
| 09f74eb37c | |||
| 9227973a7a | |||
| 5011543198 | |||
| d07b63c365 | |||
| c12e27dbfe | |||
| 4ea32b94ed | |||
| fe93d5236c | |||
| 5992394bca | |||
| 6c9f5800e5 | |||
| 227cebcb0b | |||
| 6fd4cc6b3f | |||
| 594c8965c1 | |||
| 2241145a17 | |||
| 34f252b1c9 | |||
| 89e1d7bc84 | |||
| f0368deda2 | |||
| 4028551fd8 | |||
| 06f385a28e | |||
| 44aeff425b | |||
| 35a38d719c | |||
| f6ba81e8b7 | |||
| 64cb55fd5d | |||
| 13fe38517c | |||
| 3bdb501d1d | |||
| b8adbf4b07 | |||
| aa85a9950c | |||
| 8e63efee1b | |||
| ea98f03aeb | |||
| 90cd6226be | |||
| 9d2df64b2e | |||
| bade86a24f | |||
| c3b57b4888 | |||
| fcfedc5414 | |||
| 8dee0da434 | |||
| e4ab024422 | |||
| 2bd01c4014 | |||
| 034c7e385c | |||
| c9086747a3 | |||
| ab1ed269fd | |||
| f7a823e9bc | |||
| b6301b08f8 | |||
| 265c219fdc | |||
| 729db694a3 | |||
| e2e6415cb6 | |||
| 419104a4ec | |||
| f18eac2001 | |||
| 7bffbe59ed | |||
| bf53b4f5eb | |||
| 21440230f3 | |||
| 99c27ba8ef | |||
| cb7a925cd0 | |||
| d2e11bd7df | |||
| 1b74a3720e | |||
| e222af335e | |||
| 599e6270e8 | |||
| da7ddcd4f1 | |||
| bd01039fb8 | |||
| 718f01ccd4 | |||
| fd3742b926 | |||
| e8b954d1bd | |||
| 58042decd5 | |||
| fa500b3865 | |||
| e03924fe9d | |||
| 3f308a2d3b | |||
| 6cdd93bab0 | |||
| 69c6c883c2 | |||
| 69dcf1299b | |||
| b6cd78ca4c | |||
| d18116bd7d | |||
| 6b30c2028b | |||
| 8c4a358072 | |||
| fe8482fc71 | |||
| 28217df654 | |||
| 3723697add | |||
| b3e3839fb5 | |||
| 89ee58590c | |||
| 326508e567 | |||
| 21e01bc1db | |||
| ed58dfaef6 | |||
| c2c0e2809c | |||
| bafda5ca46 | |||
| a7eaf5dbe4 | |||
| 805a287129 | |||
| 61fe16cab4 | |||
| 33085a0e3c | |||
| 2df09a20f1 | |||
| a7d61b802d | |||
| 88bcb1c2b4 | |||
| af194c1851 | |||
| 71193727c9 | |||
| bc7571832a | |||
| e379e13802 | |||
| 4484765358 | |||
| 5d4ea2a308 | |||
| 0db9f9df0c | |||
| 9301e67e3f | |||
| a019403b1b | |||
| c99d7ee677 | |||
| 94a2306b7f | |||
| 73bd28aeb8 | |||
| 904f2641c5 | |||
| 4372195547 | |||
| 14f8094a9d | |||
| 4770c27d7d | |||
| f4baf308a4 | |||
| 6f852ab88a | |||
| 14bb6edec8 | |||
| b4a7c724db | |||
| 9fb4b4dec5 | |||
| 4bbc92ccaf | |||
| dd12662b17 | |||
| c364de1b17 | |||
| a06e8e3039 | |||
| b9021cb664 | |||
| a2c3fa2cc5 | |||
| 517f3bd1b8 | |||
| 29b4b92fab | |||
| e8f046f02e | |||
| 2bf6778c8a | |||
| e11c713ce3 | |||
| b7189595bd | |||
| c5d4a62930 | |||
| 378f216f6d | |||
| 7654c30b1b | |||
| f4767ffb26 | |||
| e06639daa5 | |||
| 9bd23ffac8 | |||
| 60f5d29570 | |||
| b2497e5f81 | |||
| 771a447e2c | |||
| a964f1d841 | |||
| 57d5356bfe | |||
| fd29487121 | |||
| 5fb6797577 | |||
| 3d0f77ab0b | |||
| dbc249b6bc | |||
| 08c6218440 | |||
| 737c933b8c | |||
| b9ab87a308 | |||
| 2e5cb58c39 | |||
| db622e7458 | |||
| 09bbf98e61 | |||
| ca90ff2767 | |||
| 368dd16c9b | |||
| 251648f53c | |||
| ffa5b6b2ad | |||
| bd9beaa343 | |||
| 3e4decdfb9 | |||
| 165907d144 | |||
| 6278417423 | |||
| dc37f565c4 | |||
| 532196a9b4 | |||
| 6a4009e13a | |||
| a8f98e51bb | |||
| 2b03bc798e | |||
| 482556d378 | |||
| deb525af6e | |||
| cb2bfbb91c | |||
| 654395a175 | |||
| e31b60bc48 | |||
| 183953f4c4 | |||
| 98d15143c2 | |||
| a24d8d3ebc | |||
| 4ca574c581 | |||
| c7ce8c87dd | |||
| f64d546672 | |||
| 96187870b4 | |||
| d4a1f1a784 | |||
| e07532961e | |||
| 450c265ded | |||
| f8502c3ca8 | |||
| 899da6990d | |||
| e7675f938e | |||
| b08138e9e0 | |||
| 5df4abdc4b | |||
| a2fa8afa72 | |||
| 7670cd67dc | |||
| 8446ac2b27 | |||
| 63a80e44d5 | |||
| 076df75322 | |||
| 11db99da73 | |||
| 050dca5a50 | |||
| 3c096f1386 | |||
| 0f3e8fce3b | |||
| 325f90bba5 | |||
| a739a938fc | |||
| b30e3a9b11 | |||
| fc1a7c7438 | |||
| 6046113cb1 | |||
| 611ffafec5 | |||
| c497b906df | |||
| c68fce19f9 | |||
| f8913531b6 | |||
| 30f76e2088 | |||
| 39556892cd | |||
| 2fd66bf748 | |||
| d4f1428d5f | |||
| 189141c84d | |||
| f8ccfece09 | |||
| 9a7c926d53 | |||
| c5c1674153 | |||
| 8562ee5414 | |||
| 06c66a756c | |||
| b66d07d21b | |||
| 05001b6a79 | |||
| f02f4ba9d3 | |||
| fbace98aac | |||
| 8f0af3dcd6 | |||
| e8e44c5dc8 | |||
| ac33164342 | |||
| 5c7c0d84ea | |||
| 7ca725ac37 | |||
| 510a4b3dbb | |||
| 0f130ab1b8 | |||
| 25114009e3 | |||
| 79c16d74ce | |||
| 742e1e445a | |||
| 386f96d60e | |||
| 82d85af672 | |||
| 4d1b267688 | |||
| bc99ad63a6 | |||
| 4bb44f8c93 | |||
| c72265ed50 | |||
| b8958c9eb6 | |||
| e33e314cb7 | |||
| 84cebee9da | |||
| 34d3cf7ae8 | |||
| 93d0da836a | |||
| fd51276948 | |||
| d6274854ba | |||
| ea4bd1a31d | |||
| 286e047963 | |||
| be16f48f3d | |||
| ebea1e0813 | |||
| cc8d08f829 | |||
| aacffc22eb | |||
| d71ca4ffb9 | |||
| 186004f7f8 | |||
| c2eb22d666 | |||
| af189b15b6 | |||
| 1c19be85c3 | |||
| 4bb4362d23 | |||
| f6f66b3ae6 | |||
| b4ccecbcf1 | |||
| 92f1f196bb | |||
| ee14070a7b | |||
| 8ce7e14a02 | |||
| 3401ca049e | |||
| 5dcc7b9efd | |||
| 06a538bb81 | |||
| 7ab0419f27 | |||
| a7275aaa42 | |||
| bc4e6a05ea | |||
| ca170f5a87 | |||
| 22e7e96dfa | |||
| fcfd1ddb7a | |||
| daf8c9265b | |||
| 406d098172 | |||
| 824d2e3e8d | |||
| 3cd975dbbd | |||
| 8e50c36a71 | |||
| b499741ab4 | |||
| b409cdb913 | |||
| 13e56105e3 | |||
| f68e86e4cf | |||
| da996c1f33 | |||
| 0990ce4678 | |||
| bb6fb2f49d | |||
| 400296575e | |||
| d58c790b1f | |||
| c674c2ab9e | |||
| d79692cf3b | |||
| 353c2479f1 | |||
| 0176a854b8 | |||
| 00548ea908 | |||
| 09e335a8a7 | |||
| 53e2ed253f | |||
| 06b035d9ac | |||
| 5c88cbcc42 | |||
| d9b175a676 | |||
| f5b9bc95c6 | |||
| 586dcdea0d | |||
| 50957fc179 | |||
| c725e4744b | |||
| 7479ce237e | |||
| 84420441c0 | |||
| ac96721e87 | |||
| db4c7f5e32 | |||
| 87dc78eea0 | |||
| e9c2898056 | |||
| b9c4570137 | |||
| 8e2525cc6c | |||
| 8862a93f23 | |||
| 82efd88920 | |||
| 0ef528d296 | |||
| 4c33a5d88c | |||
| d64d06181b | |||
| ef9cf2db22 | |||
| 96c295a003 | |||
| 22528f5b66 | |||
| 1cd9c72537 | |||
| 7253b43eb4 | |||
| 181964cf03 | |||
| 5914245ae4 | |||
| 1bf3d28d4e | |||
| dbcbd93ace | |||
| 1729c6a308 | |||
| 019493cbfa | |||
| 60540ba966 | |||
| 601ad419ec | |||
| 80e7bab891 | |||
| f5c8befbf0 | |||
| 09c984baa7 | |||
| 0d93260672 | |||
| 3e9e217f92 | |||
| 3cd8859c62 | |||
| 4493b4a419 | |||
| 79e3e70bd6 | |||
| 56a955befd | |||
| 496c28f80d | |||
| 7a59f3fe0c | |||
| 3d6875a532 | |||
| 15bf380f4f | |||
| 0b910db039 | |||
| 0e5e8f602f | |||
| d9db0f9401 | |||
| c0da7c7339 | |||
| 7e7599b4a7 | |||
| 99cd88e6c6 | |||
| 053a06229c | |||
| 1a6e8280a8 | |||
| 125e8be83c | |||
| 4d89ca2101 | |||
| e8aee3bb32 | |||
| d3c7ca75f0 | |||
| 694d5f56d5 | |||
| a48439785c | |||
| 7c9bd84f00 | |||
| 799d212d9b | |||
| fa15502ce7 | |||
| 1f4d3bf784 | 
							
								
								
									
										12
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								.env.example
									
									
									
									
									
								
							| @ -9,12 +9,13 @@ DB_HOST=db | ||||
| DB_PORT=3306 | ||||
| DB_DATABASE=crater | ||||
| DB_USERNAME=crater | ||||
| DB_PASSWORD=crater | ||||
| DB_PASSWORD="crater" | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
| SESSION_DRIVER=cookie | ||||
| SESSION_LIFETIME=1440 | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| @ -31,6 +32,7 @@ PUSHER_APP_ID= | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
|  | ||||
| PROXY_OAUTH_CLIENT_ID=2 | ||||
| PROXY_OAUTH_CLIENT_SECRET=SECRET-GENERATED-KEY-HERE | ||||
| PROXY_OAUTH_GRANT_TYPE=password | ||||
| SANCTUM_STATEFUL_DOMAINS=crater.test | ||||
| SESSION_DOMAIN=crater.test | ||||
|  | ||||
| TRUSTED_PROXIES="*" | ||||
|  | ||||
| @ -2,3 +2,12 @@ APP_ENV=testing | ||||
| APP_DEBUG=true | ||||
| APP_KEY=base64:IdDlpLmYyWA9z4Ruj5st1FSYrhCR7lPOscLGCz2Jf4I= | ||||
| DB_CONNECTION=sqlite | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=587 | ||||
| MAIL_USERNAME=ff538f0e1037f4 | ||||
| MAIL_PASSWORD=c04c81145fcb73 | ||||
| MAIL_ENCRYPTION=tls | ||||
| MAIL_FROM_ADDRESS="admin@crater.com" | ||||
| MAIL_FROM_NAME="John Doe" | ||||
|  | ||||
							
								
								
									
										10
									
								
								.eslintrc
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								.eslintrc
									
									
									
									
									
								
							| @ -1,10 +0,0 @@ | ||||
| { | ||||
|   "root": true, | ||||
|   "extends": [ | ||||
|     "plugin:vue/recommended", | ||||
|     "standard" | ||||
|   ], | ||||
|   "rules": { | ||||
|     "vue/max-attributes-per-line" : 3 | ||||
|   } | ||||
| } | ||||
							
								
								
									
										20
									
								
								.eslintrc.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								.eslintrc.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| module.exports = { | ||||
|   root: true, | ||||
|   env: { | ||||
|     node: true, | ||||
|   }, | ||||
|   extends: [ | ||||
|     'plugin:vue/recommended', | ||||
|     'eslint:recommended', | ||||
|     'prettier/vue', | ||||
|     'plugin:prettier/recommended', | ||||
|   ], | ||||
|   parserOptions: { | ||||
|     parser: 'babel-eslint', | ||||
|   }, | ||||
|   plugins: ['prettier'], | ||||
|   rules: { | ||||
|     'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', | ||||
|     'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off', | ||||
|   }, | ||||
| } | ||||
							
								
								
									
										37
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								.github/workflows/ci.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| name: CI | ||||
|  | ||||
| on: [push, pull_request] | ||||
|  | ||||
| jobs: | ||||
|   build-test: | ||||
|     runs-on: ubuntu-latest | ||||
|     strategy: | ||||
|       fail-fast: false | ||||
|       matrix: | ||||
|         php: ['7.4', '8.0'] | ||||
|  | ||||
|     name: PHP ${{ matrix.php }} | ||||
|  | ||||
|     steps: | ||||
|     - name: Checkout | ||||
|       uses: actions/checkout@v2 | ||||
|  | ||||
|     - name: Install dependencies | ||||
|       uses: shivammathur/setup-php@v2 | ||||
|       with: | ||||
|         php-version: ${{ matrix.php }} | ||||
|         extensions: exif | ||||
|  | ||||
|     - name: Install PHP 7 dependencies | ||||
|       run: composer update --no-interaction --no-progress | ||||
|       if: "matrix.php < 8" | ||||
|  | ||||
|     - name: Install PHP 8 dependencies | ||||
|       run: composer update --ignore-platform-req=php --no-interaction --no-progress | ||||
|       if: "matrix.php >= 8" | ||||
|  | ||||
|     - name: Check coding style | ||||
|       run: ./vendor/bin/php-cs-fixer fix -v --dry-run --using-cache=no --config=.php-cs-fixer.dist.php | ||||
|  | ||||
|     - name: Unit Tests | ||||
|       run: php ./vendor/bin/pest | ||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -11,5 +11,4 @@ Homestead.yaml | ||||
| .rnd | ||||
| /.expo | ||||
| /.vscode | ||||
| docker-compose.yml | ||||
| docker-compose.yaml | ||||
| /docker-compose/db/data/ | ||||
							
								
								
									
										42
									
								
								.php-cs-fixer.dist.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								.php-cs-fixer.dist.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| <?php | ||||
|  | ||||
| $finder = PhpCsFixer\Finder::create() | ||||
|     ->in(__DIR__) | ||||
|     ->exclude(['bootstrap', 'storage', 'vendor']) | ||||
|     ->name('*.php') | ||||
|     ->name('_ide_helper') | ||||
|     ->notName('*.blade.php') | ||||
|     ->ignoreDotFiles(true) | ||||
|     ->ignoreVCS(true); | ||||
|  | ||||
| $rules = [ | ||||
|     '@PSR12' => true, | ||||
|     'array_syntax' => ['syntax' => 'short'], | ||||
|     'ordered_imports' => ['sort_algorithm' => 'alpha'], | ||||
|     'concat_space' => true, | ||||
|     'no_unused_imports' => true, | ||||
|     'not_operator_with_successor_space' => true, | ||||
|     'phpdoc_scalar' => true, | ||||
|     'unary_operator_spaces' => true, | ||||
|     'binary_operator_spaces' => true, | ||||
|     'blank_line_before_statement' => [ | ||||
|         'statements' => ['break', 'continue', 'declare', 'return', 'throw', 'try'], | ||||
|     ], | ||||
|     'phpdoc_single_line_var_spacing' => true, | ||||
|     'phpdoc_var_without_name' => true, | ||||
|     'class_attributes_separation' => [ | ||||
|         'elements' => [ | ||||
|             'method' => 'one', | ||||
|             'property' => 'one', | ||||
|         ], | ||||
|     ], | ||||
|     'method_argument_space' => [ | ||||
|         'on_multiline' => 'ensure_fully_multiline', | ||||
|         'keep_multiple_spaces_after_comma' => true, | ||||
|     ], | ||||
| ]; | ||||
|  | ||||
| return (new PhpCsFixer\Config()) | ||||
|     ->setUsingCache(true) | ||||
|     ->setRules($rules) | ||||
|     ->setFinder($finder); | ||||
							
								
								
									
										5
									
								
								.prettierrc.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								.prettierrc.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|   "semi": false, | ||||
|   "singleQuote": true, | ||||
|   "tabWidth": 2 | ||||
| } | ||||
							
								
								
									
										73
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -1,52 +1,39 @@ | ||||
| ##### STAGE 1 ##### | ||||
| FROM php:7.4-fpm | ||||
|  | ||||
| FROM composer as composer | ||||
| # Arguments defined in docker-compose.yml | ||||
| ARG user | ||||
| ARG uid | ||||
|  | ||||
| # Copy composer files from project root into composer container's working dir | ||||
| COPY composer.* /app/ | ||||
| # Install system dependencies | ||||
| RUN apt-get update && apt-get install -y \ | ||||
|     git \ | ||||
|     curl \ | ||||
|     libpng-dev \ | ||||
|     libonig-dev \ | ||||
|     libxml2-dev \ | ||||
|     zip \ | ||||
|     unzip \  | ||||
|     libzip-dev \  | ||||
|     libmagickwand-dev | ||||
|  | ||||
| # Copy database directory for autoloader optimization | ||||
| COPY database /app/database | ||||
| # Clear cache | ||||
| RUN apt-get clean && rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
| # Run composer to build dependencies in vendor folder | ||||
| RUN composer install --no-scripts --no-suggest --no-interaction --prefer-dist --optimize-autoloader  | ||||
| RUN pecl install imagick \  | ||||
|     && docker-php-ext-enable imagick | ||||
|  | ||||
| # Copy everything from project root into composer container's working dir | ||||
| COPY . /app | ||||
| # Install PHP extensions | ||||
| RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl bcmath gd  | ||||
|  | ||||
| RUN composer dump-autoload --optimize --classmap-authoritative | ||||
| # Get latest Composer | ||||
| COPY --from=composer:latest /usr/bin/composer /usr/bin/composer | ||||
|  | ||||
| ##### STAGE 2 ##### | ||||
| # Create system user to run Composer and Artisan Commands | ||||
| RUN useradd -G www-data,root -u $uid -d /home/$user $user | ||||
| RUN mkdir -p /home/$user/.composer && \ | ||||
|     chown -R $user:$user /home/$user | ||||
|  | ||||
| FROM php:7.3.12-fpm-alpine | ||||
|  | ||||
| # Use the default production configuration | ||||
| RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" | ||||
|  | ||||
| RUN apk add --no-cache libpng-dev libxml2-dev oniguruma-dev && \ | ||||
|     docker-php-ext-install bcmath ctype json gd mbstring pdo pdo_mysql tokenizer xml | ||||
|  | ||||
| # Set container's working dir | ||||
| WORKDIR /app | ||||
|   | ||||
| # Copy everything from project root into php container's working dir | ||||
| COPY . /app | ||||
|  | ||||
| # Copy vendor folder from composer container into php container | ||||
| COPY --from=composer /app/vendor /app/vendor | ||||
|  | ||||
| RUN touch database/database.sqlite && \ | ||||
|     cp .env.example .env && \ | ||||
|     php artisan config:cache && \ | ||||
|     php artisan passport:keys && \ | ||||
|     php artisan key:generate && \ | ||||
|     chown -R www-data:www-data . && \ | ||||
|     chmod -R 755 . && \ | ||||
|     chmod -R 775 storage/framework/ && \ | ||||
|     chmod -R 775 storage/logs/ && \ | ||||
|     chmod -R 775 bootstrap/cache/   | ||||
|  | ||||
| EXPOSE 9000 | ||||
|  | ||||
| CMD ["php-fpm", "--nodaemonize"] | ||||
| # Set working directory | ||||
| WORKDIR /var/www | ||||
|  | ||||
| USER $user | ||||
|  | ||||
							
								
								
									
										3274
									
								
								_ide_helper.php
									
									
									
									
									
								
							
							
						
						
									
										3274
									
								
								_ide_helper.php
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,36 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Crater\User; | ||||
| use Crater\Country; | ||||
|  | ||||
| class Address extends Model | ||||
| { | ||||
|     const BILLING_TYPE = 'BILLING'; | ||||
|     const SHIPPING_TYPE = 'SHIPPING'; | ||||
|  | ||||
|     protected $fillable = [ | ||||
|         'name', | ||||
|         'address_street_1', | ||||
|         'address_street_2', | ||||
|         'city', | ||||
|         'state', | ||||
|         'country_id', | ||||
|         'zip', | ||||
|         'phone', | ||||
|         'fax', | ||||
|         'type', | ||||
|         'user_id' | ||||
|     ]; | ||||
|  | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo(User::class); | ||||
|     } | ||||
|  | ||||
|     public function country() | ||||
|     { | ||||
|         return $this->belongsTo(Country::class); | ||||
|     } | ||||
| } | ||||
| @ -1,36 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Crater\User; | ||||
| use Crater\CompanySetting; | ||||
| use Spatie\MediaLibrary\HasMedia\HasMedia; | ||||
| use Spatie\MediaLibrary\HasMedia\HasMediaTrait; | ||||
|  | ||||
| class Company extends Model implements HasMedia | ||||
| { | ||||
|     use HasMediaTrait; | ||||
|  | ||||
|     protected $fillable = ['name', 'logo', 'unique_hash']; | ||||
|  | ||||
|     protected $appends=['logo']; | ||||
|  | ||||
|     public function getLogoAttribute() | ||||
|     { | ||||
|         $logo = $this->getMedia('logo')->first(); | ||||
|         if ($logo) { | ||||
|             return  asset($logo->getUrl()); | ||||
|         } | ||||
|         return ; | ||||
|     } | ||||
|  | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->hasOne(User::class); | ||||
|     } | ||||
|  | ||||
|     public function settings() | ||||
|     { | ||||
|         return $this->hasMany(CompanySetting::class); | ||||
|     } | ||||
| } | ||||
| @ -1,47 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
|  | ||||
| class CompanySetting extends Model | ||||
| { | ||||
|     protected $fillable = ['company_id', 'option', 'value']; | ||||
|  | ||||
|     public function company() | ||||
|     { | ||||
|         return $this->belongsTo(Company::class); | ||||
|     } | ||||
|  | ||||
|     public static function setSetting($key, $setting, $company_id) | ||||
|     { | ||||
|         $old = self::whereOption($key)->whereCompany($company_id)->first(); | ||||
|  | ||||
|         if ($old) { | ||||
|             $old->value = $setting; | ||||
|             $old->save(); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $set = new CompanySetting(); | ||||
|         $set->option = $key; | ||||
|         $set->value = $setting; | ||||
|         $set->company_id = $company_id; | ||||
|         $set->save(); | ||||
|     } | ||||
|  | ||||
|     public static function getSetting($key, $company_id) | ||||
|     { | ||||
|         $setting = static::whereOption($key)->whereCompany($company_id)->first(); | ||||
|  | ||||
|         if ($setting) { | ||||
|             return $setting->value; | ||||
|         } else { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereCompany($query, $company_id) | ||||
|     { | ||||
|         $query->where('company_id', $company_id); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console\Commands; | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
| use Carbon\Carbon; | ||||
| use Crater\Estimate; | ||||
| use Crater\Models\Estimate; | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| class CheckEstimateStatus extends Command | ||||
| { | ||||
| @ -39,7 +40,7 @@ class CheckEstimateStatus extends Command | ||||
|     public function handle() | ||||
|     { | ||||
|         $date = Carbon::now(); | ||||
|         $status = array(Estimate::STATUS_ACCEPTED, Estimate::STATUS_REJECTED, Estimate::STATUS_EXPIRED); | ||||
|         $status = [Estimate::STATUS_ACCEPTED, Estimate::STATUS_REJECTED, Estimate::STATUS_EXPIRED]; | ||||
|         $estimates = Estimate::whereNotIn('status', $status)->whereDate('expiry_date', '<', $date)->get(); | ||||
|  | ||||
|         foreach ($estimates as $estimate) { | ||||
|  | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console\Commands; | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
| use Carbon\Carbon; | ||||
| use Crater\Invoice; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| class CheckInvoiceStatus extends Command | ||||
| { | ||||
| @ -39,7 +40,7 @@ class CheckInvoiceStatus extends Command | ||||
|     public function handle() | ||||
|     { | ||||
|         $date = Carbon::now(); | ||||
|         $invoices = Invoice::where('status', '<>', Invoice::STATUS_COMPLETED)->whereDate('due_date', '<',$date)->get(); | ||||
|         $invoices = Invoice::where('status', '<>', Invoice::STATUS_COMPLETED)->whereDate('due_date', '<', $date)->get(); | ||||
|  | ||||
|         foreach ($invoices as $invoice) { | ||||
|             $invoice->status = Invoice::STATUS_OVERDUE; | ||||
|  | ||||
							
								
								
									
										68
									
								
								app/Console/Commands/ResetApp.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								app/Console/Commands/ResetApp.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,68 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console\Commands; | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Console\ConfirmableTrait; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
|  | ||||
| class ResetApp extends Command | ||||
| { | ||||
|     use ConfirmableTrait; | ||||
|  | ||||
|     /** | ||||
|      * The name and signature of the console command. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $signature = 'reset:app {--force}'; | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Clean database, database_created and public/storage folder'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle() | ||||
|     { | ||||
|         if (! $this->confirmToProceed()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $this->info('Running migrate:fresh'); | ||||
|  | ||||
|         Artisan::call('migrate:fresh --seed --force'); | ||||
|  | ||||
|         $this->info('Seeding database'); | ||||
|  | ||||
|         Artisan::call('db:seed', ['--class' => 'DemoSeeder', '--force' => true]); | ||||
|  | ||||
|         $path = base_path('.env'); | ||||
|  | ||||
|         if (file_exists($path)) { | ||||
|             file_put_contents($path, str_replace( | ||||
|                 'APP_DEBUG=true', | ||||
|                 'APP_DEBUG=false', | ||||
|                 file_get_contents($path) | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         $this->info('App has been reset successfully'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										241
									
								
								app/Console/Commands/UpdateCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										241
									
								
								app/Console/Commands/UpdateCommand.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,241 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console\Commands; | ||||
|  | ||||
| use Crater\Models\Setting; | ||||
| use Crater\Space\Updater; | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| // Implementation taken from Akaunting - https://github.com/akaunting/akaunting | ||||
| class UpdateCommand extends Command | ||||
| { | ||||
|     public $installed; | ||||
|  | ||||
|     public $version; | ||||
|  | ||||
|     public $response; | ||||
|  | ||||
|     /** | ||||
|      * The name and signature of the console command. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $signature = 'crater:update'; | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Automatically update your crater app'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
|     public function handle() | ||||
|     { | ||||
|         set_time_limit(3600); // 1 hour | ||||
|  | ||||
|         $this->installed = $this->getInstalledVersion(); | ||||
|         $this->response = $this->getLatestVersionResponse(); | ||||
|         $this->version = ($this->response) ? $this->response->version : false; | ||||
|  | ||||
|         if ($this->response == 'extension_required') { | ||||
|             $this->info('Sorry! Your system does not meet the minimum requirements for this update.'); | ||||
|             $this->info('Please retry after installing the required version/extensions.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (! $this->version) { | ||||
|             $this->info('No Update Available! You are already on the latest version.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (! $this->confirm("Do you wish to update to {$this->version}?")) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (! $path = $this->download()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (! $path = $this->unzip($path)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (! $this->copyFiles($path)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (isset($this->response->deleted_files) && ! empty($this->response->deleted_files)) { | ||||
|             if (! $this->deleteFiles($this->response->deleted_files)) { | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (! $this->migrateUpdate()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (! $this->finish()) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $this->info('Successfully updated to '.$this->version); | ||||
|     } | ||||
|  | ||||
|     public function getInstalledVersion() | ||||
|     { | ||||
|         return Setting::getSetting('version'); | ||||
|     } | ||||
|  | ||||
|     public function getLatestVersionResponse() | ||||
|     { | ||||
|         $this->info('Your currently installed version is '.$this->installed); | ||||
|         $this->line(''); | ||||
|         $this->info('Checking for update...'); | ||||
|  | ||||
|         try { | ||||
|             $response = Updater::checkForUpdate($this->installed); | ||||
|  | ||||
|             if ($response->success) { | ||||
|                 $extensions = $response->version->extensions; | ||||
|  | ||||
|                 $is_required = false; | ||||
|  | ||||
|                 foreach ($extensions as $key => $extension) { | ||||
|                     if (! $extension) { | ||||
|                         $is_required = true; | ||||
|                         $this->info('❌ '.$key); | ||||
|                     } | ||||
|  | ||||
|                     $this->info('✅ '.$key); | ||||
|                 } | ||||
|  | ||||
|                 if ($is_required) { | ||||
|                     return 'extension_required'; | ||||
|                 } | ||||
|  | ||||
|                 return $response->version; | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function download() | ||||
|     { | ||||
|         $this->info('Downloading update...'); | ||||
|  | ||||
|         try { | ||||
|             $path = Updater::download($this->version, 1); | ||||
|             if (! is_string($path)) { | ||||
|                 $this->error('Download exception'); | ||||
|  | ||||
|                 return false; | ||||
|             } | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return $path; | ||||
|     } | ||||
|  | ||||
|     public function unzip($path) | ||||
|     { | ||||
|         $this->info('Unzipping update package...'); | ||||
|  | ||||
|         try { | ||||
|             $path = Updater::unzip($path); | ||||
|             if (! is_string($path)) { | ||||
|                 $this->error('Unzipping exception'); | ||||
|  | ||||
|                 return false; | ||||
|             } | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return $path; | ||||
|     } | ||||
|  | ||||
|     public function copyFiles($path) | ||||
|     { | ||||
|         $this->info('Copying update files...'); | ||||
|  | ||||
|         try { | ||||
|             Updater::copyFiles($path); | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public function deleteFiles($files) | ||||
|     { | ||||
|         $this->info('Deleting unused old files...'); | ||||
|  | ||||
|         try { | ||||
|             Updater::deleteFiles($files); | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public function migrateUpdate() | ||||
|     { | ||||
|         $this->info('Running Migrations...'); | ||||
|  | ||||
|         try { | ||||
|             Updater::migrateUpdate(); | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     public function finish() | ||||
|     { | ||||
|         $this->info('Finishing update...'); | ||||
|  | ||||
|         try { | ||||
|             Updater::finishUpdate($this->installed, $this->version); | ||||
|         } catch (\Exception $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| @ -1,4 +1,5 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console; | ||||
|  | ||||
| use Illuminate\Console\Scheduling\Schedule; | ||||
| @ -12,7 +13,8 @@ class Kernel extends ConsoleKernel | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $commands = [ | ||||
|  | ||||
|         Commands\ResetApp::class, | ||||
|         Commands\UpdateCommand::class, | ||||
|     ]; | ||||
|  | ||||
|     /** | ||||
|  | ||||
							
								
								
									
										237
									
								
								app/Estimate.php
									
									
									
									
									
								
							
							
						
						
									
										237
									
								
								app/Estimate.php
									
									
									
									
									
								
							| @ -1,237 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Crater\CompanySetting; | ||||
| use Carbon\Carbon; | ||||
|  | ||||
| class Estimate extends Model | ||||
| { | ||||
|     const STATUS_DRAFT = 'DRAFT'; | ||||
|     const STATUS_SENT = 'SENT'; | ||||
|     const STATUS_VIEWED = 'VIEWED'; | ||||
|     const STATUS_EXPIRED = 'EXPIRED'; | ||||
|     const STATUS_ACCEPTED = 'ACCEPTED'; | ||||
|     const STATUS_REJECTED = 'REJECTED'; | ||||
|  | ||||
|     protected $dates = [ | ||||
|         'created_at', | ||||
|         'updated_at', | ||||
|         'deleted_at', | ||||
|         'estimate_date', | ||||
|         'expiry_date' | ||||
|     ]; | ||||
|  | ||||
|     protected $appends = [ | ||||
|         'formattedExpiryDate', | ||||
|         'formattedEstimateDate' | ||||
|     ]; | ||||
|  | ||||
|     protected $fillable = [ | ||||
|         'estimate_date', | ||||
|         'expiry_date', | ||||
|         'estimate_number', | ||||
|         'user_id', | ||||
|         'company_id', | ||||
|         'reference_number', | ||||
|         'estimate_template_id', | ||||
|         'discount', | ||||
|         'discount_type', | ||||
|         'discount_val', | ||||
|         'status', | ||||
|         'sub_total', | ||||
|         'tax_per_item', | ||||
|         'discount_per_item', | ||||
|         'total', | ||||
|         'tax', | ||||
|         'notes', | ||||
|         'unique_hash' | ||||
|     ]; | ||||
|  | ||||
|     protected $casts = [ | ||||
|         'total' => 'integer', | ||||
|         'tax' => 'integer', | ||||
|         'sub_total' => 'integer', | ||||
|         'discount' => 'float', | ||||
|         'discount_val' => 'integer', | ||||
|     ]; | ||||
|  | ||||
|     public static function getNextEstimateNumber($value) | ||||
|     { | ||||
|          // Get the last created order | ||||
|          $lastOrder = Estimate::where('estimate_number', 'LIKE', $value . '-%') | ||||
|                         ->orderBy('created_at', 'desc') | ||||
|                         ->first(); | ||||
|  | ||||
|         if (!$lastOrder) { | ||||
|             // We get here if there is no order at all | ||||
|             // If there is no number set it to 0, which will be 1 at the end. | ||||
|             $number = 0; | ||||
|         } else { | ||||
|             $number = explode("-",$lastOrder->estimate_number); | ||||
|             $number = $number[1]; | ||||
|         } | ||||
|  | ||||
|         // If we have ORD000001 in the database then we only want the number | ||||
|         // So the substr returns this 000001 | ||||
|  | ||||
|         // Add the string in front and higher up the number. | ||||
|         // the %05d part makes sure that there are always 6 numbers in the string. | ||||
|         // so it adds the missing zero's when needed. | ||||
|  | ||||
|         return sprintf('%06d', intval($number) + 1); | ||||
|     } | ||||
|  | ||||
|     public function items() | ||||
|     { | ||||
|         return $this->hasMany('Crater\EstimateItem'); | ||||
|     } | ||||
|  | ||||
|     public function user() | ||||
|     { | ||||
|         return $this->belongsTo('Crater\User'); | ||||
|     } | ||||
|  | ||||
|     public function taxes() | ||||
|     { | ||||
|         return $this->hasMany(Tax::class); | ||||
|     } | ||||
|  | ||||
|     public function estimateTemplate() | ||||
|     { | ||||
|         return $this->belongsTo('Crater\EstimateTemplate'); | ||||
|     } | ||||
|  | ||||
|     public function getEstimateNumAttribute() | ||||
|     { | ||||
|         $position = $this->strposX($this->estimate_number, "-", 1) + 1; | ||||
|         return substr($this->estimate_number, $position); | ||||
|     } | ||||
|  | ||||
|     public function getEstimatePrefixAttribute() | ||||
|     { | ||||
|         $prefix = explode("-",$this->estimate_number)[0]; | ||||
|         return $prefix; | ||||
|     } | ||||
|  | ||||
|     private function strposX($haystack, $needle, $number) | ||||
|     { | ||||
|         if ($number == '1') { | ||||
|             return strpos($haystack, $needle); | ||||
|         } elseif ($number > '1') { | ||||
|             return strpos( | ||||
|                 $haystack, | ||||
|                 $needle, | ||||
|                 $this->strposX($haystack, $needle, $number - 1) + strlen($needle) | ||||
|             ); | ||||
|         } else { | ||||
|             return error_log('Error: Value for parameter $number is out of range'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function getFormattedExpiryDateAttribute($value) | ||||
|     { | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); | ||||
|         return Carbon::parse($this->expiry_date)->format($dateFormat); | ||||
|     } | ||||
|  | ||||
|     public function getFormattedEstimateDateAttribute($value) | ||||
|     { | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); | ||||
|         return Carbon::parse($this->estimate_date)->format($dateFormat); | ||||
|     } | ||||
|  | ||||
|     public function scopeEstimatesBetween($query, $start, $end) | ||||
|     { | ||||
|         return $query->whereBetween( | ||||
|             'estimates.estimate_date', | ||||
|             [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereStatus($query, $status) | ||||
|     { | ||||
|         return $query->where('estimates.status', $status); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereEstimateNumber($query, $estimateNumber) | ||||
|     { | ||||
|         return $query->where('estimates.estimate_number', $estimateNumber); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereSearch($query, $search) | ||||
|     { | ||||
|         foreach (explode(' ', $search) as $term) { | ||||
|             $query->whereHas('user', function ($query) use ($term) { | ||||
|                 $query->where('name', 'LIKE', '%'.$term.'%') | ||||
|                     ->orWhere('contact_name', 'LIKE', '%'.$term.'%') | ||||
|                     ->orWhere('company_name', 'LIKE', '%'.$term.'%'); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function scopeApplyFilters($query, array $filters) | ||||
|     { | ||||
|         $filters = collect($filters); | ||||
|  | ||||
|         if ($filters->get('search')) { | ||||
|             $query->whereSearch($filters->get('search')); | ||||
|         } | ||||
|  | ||||
|         if ($filters->get('estimate_number')) { | ||||
|             $query->whereEstimateNumber($filters->get('estimate_number')); | ||||
|         } | ||||
|  | ||||
|         if ($filters->get('status')) { | ||||
|             $query->whereStatus($filters->get('status')); | ||||
|         } | ||||
|  | ||||
|         if ($filters->get('from_date') && $filters->get('to_date')) { | ||||
|             $start = Carbon::createFromFormat('d/m/Y', $filters->get('from_date')); | ||||
|             $end = Carbon::createFromFormat('d/m/Y', $filters->get('to_date')); | ||||
|             $query->estimatesBetween($start, $end); | ||||
|         } | ||||
|  | ||||
|         if ($filters->get('customer_id')) { | ||||
|             $query->whereCustomer($filters->get('customer_id')); | ||||
|         } | ||||
|  | ||||
|         if ($filters->get('orderByField') || $filters->get('orderBy')) { | ||||
|             $field = $filters->get('orderByField') ? $filters->get('orderByField') : 'estimate_number'; | ||||
|             $orderBy = $filters->get('orderBy') ? $filters->get('orderBy') : 'asc'; | ||||
|             $query->whereOrder($field, $orderBy); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereOrder($query, $orderByField, $orderBy) | ||||
|     { | ||||
|         $query->orderBy($orderByField, $orderBy); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereCompany($query, $company_id) | ||||
|     { | ||||
|         $query->where('estimates.company_id', $company_id); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereCustomer($query, $customer_id) | ||||
|     { | ||||
|         $query->where('estimates.user_id', $customer_id); | ||||
|     } | ||||
|  | ||||
|     public static function deleteEstimate($id) | ||||
|     { | ||||
|         $estimate = Estimate::find($id); | ||||
|  | ||||
|         if ($estimate->items()->exists()) { | ||||
|             $estimate->items()->delete(); | ||||
|         } | ||||
|  | ||||
|         if ($estimate->taxes()->exists()) { | ||||
|             $estimate->taxes()->delete(); | ||||
|         } | ||||
|  | ||||
|         $estimate->delete(); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| @ -2,13 +2,7 @@ | ||||
|  | ||||
| namespace Crater\Events; | ||||
|  | ||||
| use Illuminate\Broadcasting\Channel; | ||||
| use Illuminate\Broadcasting\InteractsWithSockets; | ||||
| use Illuminate\Broadcasting\PresenceChannel; | ||||
| use Illuminate\Broadcasting\PrivateChannel; | ||||
| use Illuminate\Contracts\Broadcasting\ShouldBroadcast; | ||||
| use Illuminate\Foundation\Events\Dispatchable; | ||||
| use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| class UpdateFinished | ||||
| { | ||||
| @ -25,7 +19,7 @@ class UpdateFinished | ||||
|      */ | ||||
|     public function __construct($old, $new) | ||||
|     { | ||||
|         $this->old   = $old; | ||||
|         $this->new   = $new; | ||||
|         $this->old = $old; | ||||
|         $this->new = $new; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,8 +1,9 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Exceptions; | ||||
|  | ||||
| use Exception; | ||||
| use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; | ||||
| use Throwable; | ||||
|  | ||||
| class Handler extends ExceptionHandler | ||||
| { | ||||
| @ -30,10 +31,10 @@ class Handler extends ExceptionHandler | ||||
|      * | ||||
|      * This is a great spot to send exceptions to Sentry, Bugsnag, etc. | ||||
|      * | ||||
|      * @param  \Exception  $exception | ||||
|      * @param  \Throwable $exception | ||||
|      * @return void | ||||
|      */ | ||||
|     public function report(Exception $exception) | ||||
|     public function report(Throwable $exception) | ||||
|     { | ||||
|         parent::report($exception); | ||||
|     } | ||||
| @ -42,10 +43,10 @@ class Handler extends ExceptionHandler | ||||
|      * Render an exception into an HTTP response. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Exception  $exception | ||||
|      * @param  \Throwable  $exception | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function render($request, Exception $exception) | ||||
|     public function render($request, Throwable $exception) | ||||
|     { | ||||
|         return parent::render($request, $exception); | ||||
|     } | ||||
|  | ||||
| @ -1,39 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater; | ||||
|  | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Crater\Expense; | ||||
| use Carbon\Carbon; | ||||
|  | ||||
| class ExpenseCategory extends Model | ||||
| { | ||||
|     protected $fillable = ['name', 'company_id', 'description']; | ||||
|  | ||||
|     /** | ||||
|      * The accessors to append to the model's array form. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $appends = ['amount', 'formattedCreatedAt']; | ||||
|  | ||||
|     public function expenses() | ||||
|     { | ||||
|         return $this->hasMany(Expense::class); | ||||
|     } | ||||
|  | ||||
|     public function getFormattedCreatedAtAttribute($value) | ||||
|     { | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id); | ||||
|         return Carbon::parse($this->created_at)->format($dateFormat); | ||||
|     } | ||||
|  | ||||
|     public function getAmountAttribute() | ||||
|     { | ||||
|         return $this->expenses()->sum('amount'); | ||||
|     } | ||||
|  | ||||
|     public function scopeWhereCompany($query, $company_id) | ||||
|     { | ||||
|         $query->where('company_id', $company_id); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										47
									
								
								app/Generators/CustomPathGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								app/Generators/CustomPathGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Generators; | ||||
|  | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Spatie\MediaLibrary\MediaCollections\Models\Media; | ||||
| use Spatie\MediaLibrary\Support\PathGenerator\PathGenerator; | ||||
|  | ||||
| class CustomPathGenerator implements PathGenerator | ||||
| { | ||||
|     public function getPath(Media $media): string | ||||
|     { | ||||
|         return $this->getBasePath($media).'/'; | ||||
|     } | ||||
|  | ||||
|     public function getPathForConversions(Media $media): string | ||||
|     { | ||||
|         return $this->getBasePath($media).'/conversations/'; | ||||
|     } | ||||
|  | ||||
|     public function getPathForResponsiveImages(Media $media): string | ||||
|     { | ||||
|         return $this->getBasePath($media).'/responsive-images/'; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Get a unique base path for the given media. | ||||
|      */ | ||||
|     protected function getBasePath(Media $media): string | ||||
|     { | ||||
|         $folderName = null; | ||||
|  | ||||
|         if ($media->model_type == Invoice::class) { | ||||
|             $folderName = 'Invoices'; | ||||
|         } elseif ($media->model_type == Estimate::class) { | ||||
|             $folderName = 'Estimates'; | ||||
|         } elseif ($media->model_type == Payment::class) { | ||||
|             $folderName = 'Payments'; | ||||
|         } else { | ||||
|             $folderName = $media->getKey(); | ||||
|         } | ||||
|  | ||||
|         return $folderName; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										24
									
								
								app/Http/Controllers/AppVersionController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Http/Controllers/AppVersionController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Crater\Models\Setting; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class AppVersionController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $version = Setting::getSetting('version'); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'version' => $version, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,194 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers\Auth; | ||||
|  | ||||
| use Crater\Proxy\HttpKernelProxy; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Http\Response; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| use Illuminate\Foundation\Auth\ThrottlesLogins; | ||||
| use Validator; | ||||
| use Hash; | ||||
| use Crater\User; | ||||
| use Auth; | ||||
| use Crater\Http\Controllers\Controller; | ||||
|  | ||||
| class AccessTokensController extends Controller | ||||
| { | ||||
| 	use ThrottlesLogins; | ||||
|  | ||||
| 	/** | ||||
| 	 * A tool for proxying requests to the existing application. | ||||
| 	 * | ||||
| 	 * @var HttpKernelProxy | ||||
| 	 */ | ||||
| 	protected $proxy; | ||||
|  | ||||
| 	/** | ||||
| 	 * Create a new controller instance. | ||||
| 	 * | ||||
| 	 * @return void | ||||
| 	 */ | ||||
| 	public function __construct(HttpKernelProxy $proxy) | ||||
| 	{ | ||||
| 		$this->middleware('api')->except(['store', 'update']); | ||||
| 		$this->proxy = $proxy; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Get the login username to be used by the controller. | ||||
| 	 * | ||||
| 	 * @return string | ||||
| 	 */ | ||||
| 	public function username() | ||||
| 	{ | ||||
| 		return 'email'; | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Generate a new access token. | ||||
| 	 * | ||||
| 	 * @param  \Illuminate\Http\Request  $request | ||||
| 	 * @return \Illuminate\Http\Response | ||||
| 	 */ | ||||
| 	public function store(Request $request) | ||||
| 	{ | ||||
| 		$request->validate([ | ||||
| 			'username' => 'required|email', | ||||
| 			'password' => 'required|string|min:8', | ||||
| 		]); | ||||
|  | ||||
| 		if ($this->hasTooManyLoginAttempts($request)) { | ||||
| 			$this->fireLockoutEvent($request); | ||||
|  | ||||
| 			return $this->sendLockoutResponse($request); | ||||
| 		} | ||||
|  | ||||
| 		return $this->requestPasswordGrant($request); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Refresh an access token. | ||||
| 	 * | ||||
| 	 * @param  \Illuminate\Http\Request  $request | ||||
| 	 * @return \Illuminate\Http\Response | ||||
| 	 */ | ||||
| 	public function update(Request $request) | ||||
| 	{ | ||||
| 		$token = $request->cookie('refresh_token'); | ||||
|  | ||||
| 		if (!$token) { | ||||
| 			throw ValidationException::withMessages([ | ||||
| 				'refresh_token' => trans('oauth.missing_refresh_token') | ||||
| 			]); | ||||
| 		} | ||||
|  | ||||
| 		$response = $this->proxy->postJson('oauth/token', [ | ||||
| 			'client_id' => config('auth.proxy.client_id'), | ||||
| 			'client_secret' => config('auth.proxy.client_secret'), | ||||
| 			'grant_type' => 'refresh_token', | ||||
| 			'refresh_token' => $token, | ||||
| 			'scopes' => '[*]', | ||||
| 		]); | ||||
|  | ||||
| 		if ($response->isSuccessful()) { | ||||
| 			return $this->sendSuccessResponse($response); | ||||
| 		} | ||||
|  | ||||
| 		return response($response->getContent(), $response->getStatusCode()); | ||||
| 	} | ||||
|  | ||||
|    /** | ||||
|      * Get the guard to be used during authentication. | ||||
|      * | ||||
|      * @return \Illuminate\Contracts\Auth\StatefulGuard | ||||
|      */ | ||||
|     protected function guard() | ||||
|     { | ||||
|         return Auth::guard('api'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(Request $request) | ||||
|     { | ||||
|         $accessToken = Auth::user()->token(); | ||||
|  | ||||
|         \DB::table('oauth_refresh_tokens') | ||||
|                 ->where('access_token_id', $accessToken->id) | ||||
|                 ->update([ | ||||
|                         'revoked' => true | ||||
|                 ]); | ||||
|  | ||||
|         $accessToken->revoke(); | ||||
|  | ||||
|         return response()->json(null, 200); | ||||
|     } | ||||
|  | ||||
| 	/** | ||||
| 	 * Create a new access token from a password grant client. | ||||
| 	 * | ||||
| 	 * @param \Illuminate\Http\Request  $request | ||||
| 	 * @return \Illuminate\Http\Response | ||||
| 	 */ | ||||
| 	public function requestPasswordGrant(Request $request) | ||||
| 	{ | ||||
| 		$response = $this->proxy->postJson('oauth/token', [ | ||||
| 			'client_id' => config('auth.proxy.client_id'), | ||||
| 			'client_secret' => config('auth.proxy.client_secret'), | ||||
| 			'grant_type' => config('auth.proxy.grant_type'), | ||||
| 			'username' => $request->username, | ||||
| 			'password' => $request->password, | ||||
| 			'scopes' => '[*]' | ||||
| 		]); | ||||
|  | ||||
|         $user = User::where('email', $request->username)->first(); | ||||
|  | ||||
|         if ($response->isSuccessful()) { | ||||
|             $this->clearLoginAttempts($request); | ||||
| 			return $this->sendSuccessResponse($response, $user); | ||||
| 		} | ||||
|  | ||||
| 		$this->incrementLoginAttempts($request); | ||||
|  | ||||
| 		return response($response->getContent(), $response->getStatusCode()); | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Return a successful response for requesting an api token. | ||||
| 	 * | ||||
| 	 * @param \Illuminate\Http\Response $response | ||||
| 	 * @return \Illuminate\Http\Response | ||||
| 	 */ | ||||
| 	public function sendSuccessResponse(Response $response, $user) | ||||
| 	{ | ||||
| 		$data = json_decode($response->getContent()); | ||||
|  | ||||
|         $content = [ | ||||
| 			'access_token' => $data->access_token, | ||||
| 			'expires_in' => $data->expires_in, | ||||
| 		]; | ||||
|  | ||||
| 		return response($content, $response->getStatusCode())->cookie( | ||||
| 			'refresh_token', | ||||
| 			$data->refresh_token, | ||||
| 			10 * 24 * 60, | ||||
| 			"", | ||||
| 			"", | ||||
| 			true, | ||||
| 			true | ||||
| 		); | ||||
|     } | ||||
|  | ||||
|     public function isRegistered(Request $request) | ||||
|     { | ||||
|         if (User::whereEmail($request->email)->first()) { | ||||
|             return 'true'; | ||||
|         } else { | ||||
|             return 'false'; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,310 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\User; | ||||
| use Crater\Setting; | ||||
| use Crater\Company; | ||||
| use Crater\Address; | ||||
| use Crater\Http\Requests\SettingRequest; | ||||
| use Crater\Http\Requests\SettingKeyRequest; | ||||
| use Crater\Http\Requests\ProfileRequest; | ||||
| use Crater\Http\Requests\CompanyRequest; | ||||
| use Crater\Http\Requests\CompanySettingRequest; | ||||
| use Crater\Http\Requests\NotificationSettingsRequest; | ||||
| use Crater\Space\CurrencyFormatter; | ||||
| use Crater\Space\DateFormatter; | ||||
| use Crater\Space\TimeZones; | ||||
| use Crater\Currency; | ||||
| use Crater\CompanySetting; | ||||
|  | ||||
| class CompanyController extends Controller | ||||
| { | ||||
|     public function getAdmin() | ||||
|     { | ||||
|         return User::find(1); | ||||
|     } | ||||
|  | ||||
|     public function updateAdminProfile(ProfileRequest $request) | ||||
|     { | ||||
|         $verifyEmail = User::where('email', $request->email)->first(); | ||||
|  | ||||
|         $user = auth()->user(); | ||||
|  | ||||
|         if ($verifyEmail) { | ||||
|             if ($verifyEmail->id !== $user->id) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'Email already in use' | ||||
|                 ]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $user->name = $request->name; | ||||
|         $user->email = $request->email; | ||||
|  | ||||
|         if ($request->has('password')) { | ||||
|             $user->password = bcrypt($request->password); | ||||
|         } | ||||
|  | ||||
|         $user->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getAdminCompany() | ||||
|     { | ||||
|         $user = User::with(['addresses', 'addresses.country', 'company'])->find(1); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function updateAdminCompany(CompanyRequest $request) | ||||
|     { | ||||
|         $user = User::find(1); | ||||
|         $company = $user->company; | ||||
|         $company->name = $request->name; | ||||
|         $company->save(); | ||||
|  | ||||
|         if ($request->has('logo')) { | ||||
|             $company->clearMediaCollection('logo'); | ||||
|             $company->addMediaFromRequest('logo')->toMediaCollection('logo'); | ||||
|         } | ||||
|  | ||||
|         $fields = $request->only(['address_street_1', 'address_street_2', 'city', 'state', 'country_id', 'zip', 'phone']); | ||||
|         $address = Address::updateOrCreate(['user_id' => 1], $fields); | ||||
|         $user = User::with(['addresses', 'addresses.country', 'company'])->find(1); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getGeneralSettings(Request $request) | ||||
|     { | ||||
|         $date_formats = DateFormatter::get_list(); | ||||
|  | ||||
|         $time_zones = TimeZones::get_list(); | ||||
|         $fiscal_years = [ | ||||
|             ['key' => 'january-december' , 'value' => '1-12'], | ||||
|             ['key' => 'february-january' , 'value' => '2-1'], | ||||
|             ['key' => 'march-february'   , 'value' => '3-2'], | ||||
|             ['key' => 'april-march'      , 'value' => '4-3'], | ||||
|             ['key' => 'may-april'        , 'value' => '5-4'], | ||||
|             ['key' => 'june-may'         , 'value' => '6-5'], | ||||
|             ['key' => 'july-june'        , 'value' => '7-6'], | ||||
|             ['key' => 'august-july'      , 'value' => '8-7'], | ||||
|             ['key' => 'september-august' , 'value' => '9-8'], | ||||
|             ['key' => 'october-september', 'value' => '10-9'], | ||||
|             ['key' => 'november-october' , 'value' => '11-10'], | ||||
|             ['key' => 'december-november', 'value' => '12-11'], | ||||
|         ]; | ||||
|  | ||||
|         $language = CompanySetting::getSetting('language', $request->header('company')); | ||||
|         $carbon_date_format = CompanySetting::getSetting('carbon_date_format', $request->header('company')); | ||||
|         $moment_date_format = CompanySetting::getSetting('moment_date_format', $request->header('company')); | ||||
|         $time_zone = CompanySetting::getSetting('time_zone', $request->header('company')); | ||||
|         $currency = CompanySetting::getSetting('currency', $request->header('company')); | ||||
|         $fiscal_year = CompanySetting::getSetting('fiscal_year', $request->header('company')); | ||||
|  | ||||
|         $languages = [ | ||||
|             ["code"=>"en", "name" => "English"], | ||||
|             ["code"=>"fr", "name" => "French"], | ||||
|             ["code"=>"es", "name" => "Spanish"] | ||||
|         ]; | ||||
|  | ||||
|         return response()->json([ | ||||
|             'languages' => $languages, | ||||
|             'date_formats' => $date_formats, | ||||
|             'time_zones' => $time_zones, | ||||
|             'time_zone' => $time_zone, | ||||
|             'currencies' => Currency::all(), | ||||
|             'fiscal_years' => $fiscal_years, | ||||
|             'fiscal_year' => $fiscal_year, | ||||
|             'selectedLanguage' => $language, | ||||
|             'selectedCurrency' => $currency, | ||||
|             'carbon_date_format' => $carbon_date_format, | ||||
|             'moment_date_format' => $moment_date_format, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function updateGeneralSettings(CompanySettingRequest $request) | ||||
|     { | ||||
|         $sets = [ | ||||
|             'currency', | ||||
|             'time_zone', | ||||
|             'language', | ||||
|             'carbon_date_format', | ||||
|             'fiscal_year', | ||||
|             'moment_date_format' | ||||
|         ]; | ||||
|  | ||||
|         foreach ($sets as $key) { | ||||
|             CompanySetting::setSetting($key, $request->$key, $request->header('company')); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getCustomizeSetting (Request $request) | ||||
|     { | ||||
|         $invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company')); | ||||
|         $invoice_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company')); | ||||
|  | ||||
|         $estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company')); | ||||
|         $estimate_auto_generate  = CompanySetting::getSetting('estimate_auto_generate', $request->header('company')); | ||||
|  | ||||
|         $payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company')); | ||||
|         $payment_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company')); | ||||
|  | ||||
|         return  response()->json([ | ||||
|             'invoice_prefix' => $invoice_prefix, | ||||
|             'invoice_auto_generate' => $invoice_auto_generate, | ||||
|             'estimate_prefix' => $estimate_prefix, | ||||
|             'estimate_auto_generate' => $estimate_auto_generate, | ||||
|             'payment_prefix' => $payment_prefix, | ||||
|             'payment_auto_generate' => $payment_auto_generate, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function updateCustomizeSetting (Request $request) | ||||
|     { | ||||
|         $sets = []; | ||||
|  | ||||
|         if ($request->type == "PAYMENTS") { | ||||
|             $sets = [ | ||||
|                 'payment_prefix' | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if ($request->type == "INVOICES") { | ||||
|             $sets = [ | ||||
|                 'invoice_prefix', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         if ($request->type == "ESTIMATES") { | ||||
|             $sets = [ | ||||
|                 'estimate_prefix', | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         foreach ($sets as $key) { | ||||
|             CompanySetting::setSetting($key, $request->$key, $request->header('company')); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function updateSetting(SettingRequest $request) | ||||
|     { | ||||
|         CompanySetting::setSetting($request->key, $request->value, $request->header('company')); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getSetting(SettingKeyRequest $request) | ||||
|     { | ||||
|         $setting = CompanySetting::getSetting($request->key, $request->header('company')); | ||||
|  | ||||
|         return response()->json([ | ||||
|             $request->key => $setting | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getColors(Request $request) | ||||
|     { | ||||
|         $colors = [ | ||||
|             'invoice_primary_color', | ||||
|             'invoice_column_heading', | ||||
|             'invoice_field_label', | ||||
|             'invoice_field_value', | ||||
|             'invoice_body_text', | ||||
|             'invoice_description_text', | ||||
|             'invoice_border_color', | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color' | ||||
|         ]; | ||||
|  | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'colorSettings' => $colorSettings | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Upload the company logo to storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function uploadCompanyLogo(Request $request) | ||||
|     { | ||||
|         $data = json_decode($request->company_logo); | ||||
|  | ||||
|         if($data) { | ||||
|             $company = Company::find($request->header('company')); | ||||
|  | ||||
|             if($company) { | ||||
|                 $company->clearMediaCollection('logo'); | ||||
|  | ||||
|                 $company->addMediaFromBase64($data->data) | ||||
|                     ->usingFileName($data->name) | ||||
|                     ->toMediaCollection('logo'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Upload the Admin Avatar to public storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function uploadAdminAvatar(Request $request) | ||||
|     { | ||||
|         $data = json_decode($request->admin_avatar); | ||||
|  | ||||
|         if($data) { | ||||
|             $user = auth()->user(); | ||||
|  | ||||
|             if($user) { | ||||
|                 $user->clearMediaCollection('admin_avatar'); | ||||
|  | ||||
|                 $user->addMediaFromBase64($data->data) | ||||
|                     ->usingFileName($data->name) | ||||
|                     ->toMediaCollection('admin_avatar'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,12 +1,15 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
|  | ||||
| class Controller extends BaseController | ||||
| { | ||||
|     use AuthorizesRequests, DispatchesJobs, ValidatesRequests; | ||||
|     use AuthorizesRequests; | ||||
|     use DispatchesJobs; | ||||
|     use ValidatesRequests; | ||||
| } | ||||
|  | ||||
| @ -1,231 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| use Crater\Conversation; | ||||
| use Crater\Group; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Notifications\CustomerAdded; | ||||
| use Crater\User; | ||||
| use Illuminate\Support\Facades\Hash; | ||||
| use Crater\Currency; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Address; | ||||
| use Illuminate\Support\Facades\DB; | ||||
|  | ||||
| class CustomersController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $customers = User::customer() | ||||
|             ->applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'contact_name', | ||||
|                 'display_name', | ||||
|                 'phone', | ||||
|                 'orderByField', | ||||
|                 'orderBy' | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('users.*', | ||||
|                 DB::raw('sum(invoices.due_amount) as due_amount') | ||||
|             ) | ||||
|             ->groupBy('users.id') | ||||
|             ->leftJoin('invoices', 'users.id', '=', 'invoices.user_id') | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         $siteData = [ | ||||
|             'customers' => $customers | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($siteData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(Requests\CustomerRequest $request) | ||||
|     { | ||||
|         $verifyEmail = User::where('email', $request->email)->first(); | ||||
|  | ||||
|  | ||||
|         $customer = new User(); | ||||
|         $customer->name = $request->name; | ||||
|         $customer->currency_id = $request->currency_id; | ||||
|         $customer->company_id = $request->header('company'); | ||||
|         $customer->email = $request->email; | ||||
|         $customer->phone = $request->phone; | ||||
|         $customer->company_name = $request->company_name; | ||||
|         $customer->contact_name = $request->contact_name; | ||||
|         $customer->website = $request->website; | ||||
|         $customer->enable_portal = $request->enable_portal; | ||||
|         $customer->role = 'customer'; | ||||
|         $customer->password = Hash::make($request->password); | ||||
|         $customer->save(); | ||||
|  | ||||
|         if ($request->addresses) { | ||||
|             foreach ($request->addresses as $address) { | ||||
|                 $newAddress = new Address(); | ||||
|                 $newAddress->name = $address["name"]; | ||||
|                 $newAddress->address_street_1 = $address["address_street_1"]; | ||||
|                 $newAddress->address_street_2 = $address["address_street_2"]; | ||||
|                 $newAddress->city = $address["city"]; | ||||
|                 $newAddress->state = $address["state"]; | ||||
|                 $newAddress->country_id = $address["country_id"]; | ||||
|                 $newAddress->zip = $address["zip"]; | ||||
|                 $newAddress->phone = $address["phone"]; | ||||
|                 $newAddress->type = $address["type"]; | ||||
|                 $newAddress->user_id = $customer->id; | ||||
|                 $newAddress->save(); | ||||
|                 $customer->addresses()->save($newAddress); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $customer = User::with('billingAddress', 'shippingAddress')->find($customer->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show($id) | ||||
|     { | ||||
|         $customer = User::with([ | ||||
|             'billingAddress', | ||||
|             'shippingAddress', | ||||
|             'billingAddress.country', | ||||
|             'shippingAddress.country', | ||||
|         ])->find($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for editing the specified resource. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function edit($id) | ||||
|     { | ||||
|         $customer = User::with('billingAddress', 'shippingAddress')->findOrFail($id); | ||||
|         $currency = $customer->currency; | ||||
|         $currencies = Currency::all(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'currencies' => $currencies, | ||||
|             'currency' => $currency | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update($id, Requests\CustomerRequest $request) | ||||
|     { | ||||
|         $customer = User::find($id); | ||||
|  | ||||
|         if ($request->email != null) { | ||||
|             $verifyEmail = User::where('email', $request->email)->first(); | ||||
|  | ||||
|             if ($verifyEmail) { | ||||
|                 if ($verifyEmail->id !== $customer->id) { | ||||
|                     return response()->json([ | ||||
|                         'success' => false, | ||||
|                         'error' => 'Email already in use' | ||||
|                     ]); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('password')) { | ||||
|             $customer->password = Hash::make($request->password); | ||||
|         } | ||||
|  | ||||
|         $customer->name = $request->name; | ||||
|         $customer->currency_id = $request->currency_id; | ||||
|         $customer->email = $request->email; | ||||
|         $customer->phone = $request->phone; | ||||
|         $customer->company_name = $request->company_name; | ||||
|         $customer->contact_name = $request->contact_name; | ||||
|         $customer->website = $request->website; | ||||
|         $customer->enable_portal = $request->enable_portal; | ||||
|         $customer->save(); | ||||
|  | ||||
|         $customer->addresses()->delete(); | ||||
|         if ($request->addresses) { | ||||
|             foreach ($request->addresses as $address) { | ||||
|                 $newAddress = $customer->addresses()->firstOrNew(['type' => $address["type"]]); | ||||
|                 $newAddress->name = $address["name"]; | ||||
|                 $newAddress->address_street_1 = $address["address_street_1"]; | ||||
|                 $newAddress->address_street_2 = $address["address_street_2"]; | ||||
|                 $newAddress->city = $address["city"]; | ||||
|                 $newAddress->state = $address["state"]; | ||||
|                 $newAddress->country_id = $address["country_id"]; | ||||
|                 $newAddress->zip = $address["zip"]; | ||||
|                 $newAddress->phone = $address["phone"]; | ||||
|                 $newAddress->type = $address["type"]; | ||||
|                 $newAddress->user_id = $customer->id; | ||||
|                 $newAddress->save(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $customer = User::with('billingAddress', 'shippingAddress')->find($customer->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy($id) | ||||
|     { | ||||
|         User::deleteCustomer($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         foreach ($request->id as $id) { | ||||
|             User::deleteCustomer($id); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,495 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Estimate; | ||||
| use Crater\EstimateItem; | ||||
| use Crater\EstimateTemplate; | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Requests\EstimatesRequest; | ||||
| use Crater\Invoice; | ||||
| use Crater\Currency; | ||||
| use Crater\User; | ||||
| use Crater\Item; | ||||
| use Validator; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Company; | ||||
| use Crater\Mail\EstimatePdf; | ||||
| use Crater\TaxType; | ||||
| use Crater\Tax; | ||||
|  | ||||
| class EstimatesController extends Controller | ||||
| { | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $estimates = Estimate::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|                 'estimateTemplate', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->join('users', 'users.id', '=', 'estimates.user_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'status', | ||||
|                 'customer_id', | ||||
|                 'estimate_number', | ||||
|                 'from_date', | ||||
|                 'to_date', | ||||
|                 'search', | ||||
|                 'orderByField', | ||||
|                 'orderBy' | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('estimates.*', 'users.name') | ||||
|             ->latest() | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         $siteData = [ | ||||
|             'estimates' => $estimates, | ||||
|             'estimateTotalCount' => Estimate::count() | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($siteData); | ||||
|     } | ||||
|  | ||||
|     public function create(Request $request) | ||||
|     { | ||||
|         $estimate_prefix = CompanySetting::getSetting('estimate_prefix', $request->header('company')); | ||||
|         $estimate_num_auto_generate = CompanySetting::getSetting('estimate_auto_generate', $request->header('company')); | ||||
|  | ||||
|         $nextEstimateNumberAttribute = null; | ||||
|         $nextEstimateNumber = Estimate::getNextEstimateNumber($estimate_prefix); | ||||
|  | ||||
|         if ($estimate_num_auto_generate == "YES") { | ||||
|             $nextEstimateNumberAttribute = $nextEstimateNumber; | ||||
|         } | ||||
|  | ||||
|         $tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company')); | ||||
|         $discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company')); | ||||
|         $customers = User::where('role', 'customer')->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customers' => $customers, | ||||
|             'nextEstimateNumberAttribute' => $nextEstimateNumberAttribute, | ||||
|             'nextEstimateNumber' => $estimate_prefix.'-'.$nextEstimateNumber, | ||||
|             'taxes' => Tax::whereCompany($request->header('company'))->latest()->get(), | ||||
|             'items' => Item::whereCompany($request->header('company'))->get(), | ||||
|             'tax_per_item' => $tax_per_item, | ||||
|             'discount_per_item' => $discount_per_item, | ||||
|             'estimateTemplates' => EstimateTemplate::all(), | ||||
|             'shareable_link' => '', | ||||
|             'estimate_prefix' => $estimate_prefix | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function store(EstimatesRequest $request) | ||||
|     { | ||||
|         $estimate_number = explode("-",$request->estimate_number); | ||||
|         $number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1])); | ||||
|  | ||||
|         Validator::make($number_attributes, [ | ||||
|             'estimate_number' => 'required|unique:estimates,estimate_number' | ||||
|         ])->validate(); | ||||
|  | ||||
|         $estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date); | ||||
|         $expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date); | ||||
|         $status = Estimate::STATUS_DRAFT; | ||||
|         $tax_per_item = CompanySetting::getSetting( | ||||
|             'tax_per_item', | ||||
|             $request->header('company') | ||||
|         ) ? CompanySetting::getSetting( | ||||
|             'tax_per_item', | ||||
|             $request->header('company') | ||||
|         ) : 'NO'; | ||||
|  | ||||
|         if ($request->has('estimateSend')) { | ||||
|             $status = Estimate::STATUS_SENT; | ||||
|         } | ||||
|  | ||||
|         $discount_per_item = CompanySetting::getSetting( | ||||
|             'discount_per_item', | ||||
|             $request->header('company') | ||||
|         ) ? CompanySetting::getSetting( | ||||
|             'discount_per_item', | ||||
|             $request->header('company') | ||||
|         ) : 'NO'; | ||||
|  | ||||
|         $estimate = Estimate::create([ | ||||
|             'estimate_date' => $estimate_date, | ||||
|             'expiry_date' => $expiry_date, | ||||
|             'estimate_number' => $number_attributes['estimate_number'], | ||||
|             'reference_number' => $request->reference_number, | ||||
|             'user_id' => $request->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'estimate_template_id' => $request->estimate_template_id, | ||||
|             'status' => $status, | ||||
|             'discount' => $request->discount, | ||||
|             'discount_type' => $request->discount_type, | ||||
|             'discount_val' => $request->discount_val, | ||||
|             'sub_total' => $request->sub_total, | ||||
|             'total' => $request->total, | ||||
|             'tax_per_item' => $tax_per_item, | ||||
|             'discount_per_item' => $discount_per_item, | ||||
|             'tax' => $request->tax, | ||||
|             'notes' => $request->notes, | ||||
|             'unique_hash' => str_random(60) | ||||
|         ]); | ||||
|  | ||||
|         $estimateItems = $request->items; | ||||
|  | ||||
|         foreach ($estimateItems as $estimateItem) { | ||||
|             $estimateItem['company_id'] = $request->header('company'); | ||||
|             $item = $estimate->items()->create($estimateItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) { | ||||
|                 foreach ($estimateItem['taxes'] as $tax) { | ||||
|                     if (gettype($tax['amount']) !== "NULL") { | ||||
|                         $tax['company_id'] = $request->header('company'); | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('taxes')) { | ||||
|             foreach ($request->taxes as $tax) { | ||||
|                 if (gettype($tax['amount']) !== "NULL") { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|                     $estimate->taxes()->create($tax); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('estimateSend')) { | ||||
|             $data['estimate'] = $estimate->toArray(); | ||||
|             $userId = $data['estimate']['user_id']; | ||||
|             $data['user'] = User::find($userId)->toArray(); | ||||
|             $data['company'] = Company::find($estimate->company_id); | ||||
|             $email = $data['user']['email']; | ||||
|             $notificationEmail = CompanySetting::getSetting( | ||||
|                 'notification_email', | ||||
|                 $request->header('company') | ||||
|             ); | ||||
|  | ||||
|             if (!$email) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'user_email_does_not_exist' | ||||
|                 ]); | ||||
|             } | ||||
|  | ||||
|             if (!$notificationEmail) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'notification_email_does_not_exist' | ||||
|                 ]); | ||||
|             } | ||||
|  | ||||
|             \Mail::to($email)->send(new EstimatePdf($data, $notificationEmail)); | ||||
|         } | ||||
|  | ||||
|         $estimate = Estimate::with([ | ||||
|             'items', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'taxes' | ||||
|         ])->find($estimate->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'estimate' => $estimate, | ||||
|             'url' => url('/estimates/pdf/'.$estimate->unique_hash), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function show(Request $request, $id) | ||||
|     { | ||||
|         $estimate = Estimate::with([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'taxes', | ||||
|             'taxes.taxType' | ||||
|         ])->find($id); | ||||
|  | ||||
|         $siteData = [ | ||||
|             'estimate' => $estimate, | ||||
|             'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash) | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($siteData); | ||||
|     } | ||||
|  | ||||
|     public function edit(Request $request,$id) | ||||
|     { | ||||
|         $estimate = Estimate::with([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'taxes', | ||||
|             'taxes.taxType' | ||||
|         ])->find($id); | ||||
|         $customers = User::where('role', 'customer')->get(); | ||||
|  | ||||
|         return response()->json( [ | ||||
|             'customers' => $customers, | ||||
|             'nextEstimateNumber' => $estimate->getEstimateNumAttribute(), | ||||
|             'taxes' => Tax::latest()->whereCompany($request->header('company'))->get(), | ||||
|             'estimate' => $estimate, | ||||
|             'items' => Item::whereCompany($request->header('company'))->latest()->get(), | ||||
|             'estimateTemplates' => EstimateTemplate::all(), | ||||
|             'tax_per_item' => $estimate->tax_per_item, | ||||
|             'discount_per_item' => $estimate->discount_per_item, | ||||
|             'shareable_link' => url('/estimates/pdf/'.$estimate->unique_hash), | ||||
|             'estimate_prefix' => $estimate->getEstimatePrefixAttribute() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function update(EstimatesRequest $request, $id) | ||||
|     { | ||||
|         $estimate_number = explode("-",$request->estimate_number); | ||||
|         $number_attributes['estimate_number'] = $estimate_number[0].'-'.sprintf('%06d', intval($estimate_number[1])); | ||||
|         Validator::make($number_attributes, [ | ||||
|             'estimate_number' => 'required|unique:estimates,estimate_number'.','.$id | ||||
|         ])->validate(); | ||||
|  | ||||
|         $estimate_date = Carbon::createFromFormat('d/m/Y', $request->estimate_date); | ||||
|         $expiry_date = Carbon::createFromFormat('d/m/Y', $request->expiry_date); | ||||
|  | ||||
|         $estimate = Estimate::find($id); | ||||
|         $estimate->estimate_date = $estimate_date; | ||||
|         $estimate->expiry_date = $expiry_date; | ||||
|         $estimate->estimate_number = $number_attributes['estimate_number']; | ||||
|         $estimate->reference_number = $request->reference_number; | ||||
|         $estimate->user_id = $request->user_id; | ||||
|         $estimate->estimate_template_id = $request->estimate_template_id; | ||||
|         $estimate->discount = $request->discount; | ||||
|         $estimate->discount_type = $request->discount_type; | ||||
|         $estimate->discount_val = $request->discount_val; | ||||
|         $estimate->sub_total = $request->sub_total; | ||||
|         $estimate->total = $request->total; | ||||
|         $estimate->tax = $request->tax; | ||||
|         $estimate->notes = $request->notes; | ||||
|         $estimate->save(); | ||||
|  | ||||
|         $oldItems = $estimate->items->toArray(); | ||||
|         $oldTaxes = $estimate->taxes->toArray(); | ||||
|         $estimateItems = $request->items; | ||||
|  | ||||
|         foreach ($oldItems as $oldItem) { | ||||
|             EstimateItem::destroy($oldItem['id']); | ||||
|         } | ||||
|  | ||||
|         foreach ($oldTaxes as $oldTax) { | ||||
|             Tax::destroy($oldTax['id']); | ||||
|         } | ||||
|  | ||||
|         foreach ($estimateItems as $estimateItem) { | ||||
|             $estimateItem['company_id'] = $request->header('company'); | ||||
|             $item = $estimate->items()->create($estimateItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $estimateItem) && $estimateItem['taxes']) { | ||||
|                 foreach ($estimateItem['taxes'] as $tax) { | ||||
|                     if (gettype($tax['amount']) !== "NULL") { | ||||
|                         $tax['company_id'] = $request->header('company'); | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('taxes')) { | ||||
|             foreach ($request->taxes as $tax) { | ||||
|                 if (gettype($tax['amount']) !== "NULL") { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|                     $estimate->taxes()->create($tax); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $estimate = Estimate::with([ | ||||
|             'items', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'taxes' | ||||
|         ])->find($estimate->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'estimate' => $estimate, | ||||
|             'url' => url('/estimates/pdf/'.$estimate->unique_hash), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function destroy($id) | ||||
|     { | ||||
|         Estimate::deleteEstimate($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function sendEstimate(Request $request) | ||||
|     { | ||||
|         $estimate = Estimate::findOrFail($request->id); | ||||
|  | ||||
|         $data['estimate'] = $estimate->toArray(); | ||||
|         $userId = $data['estimate']['user_id']; | ||||
|         $data['user'] = User::find($userId)->toArray(); | ||||
|         $data['company'] = Company::find($estimate->company_id); | ||||
|  | ||||
|         $email = $data['user']['email']; | ||||
|         $notificationEmail = CompanySetting::getSetting( | ||||
|             'notification_email', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         if (!$email) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'user_email_does_not_exist' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         if (!$notificationEmail) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'notification_email_does_not_exist' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         \Mail::to($email)->send(new EstimatePdf($data, $notificationEmail)); | ||||
|  | ||||
|         if ($estimate->status == Estimate::STATUS_DRAFT) { | ||||
|             $estimate->status = Estimate::STATUS_SENT; | ||||
|             $estimate->save(); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function markEstimateAccepted(Request $request) | ||||
|     { | ||||
|         $estimate = Estimate::find($request->id); | ||||
|         $estimate->status = Estimate::STATUS_ACCEPTED; | ||||
|         $estimate->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function markEstimateRejected(Request $request) | ||||
|     { | ||||
|         $estimate = Estimate::find($request->id); | ||||
|         $estimate->status = Estimate::STATUS_REJECTED; | ||||
|         $estimate->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function markEstimateSent(Request $request) | ||||
|     { | ||||
|         $estimate = Estimate::find($request->id); | ||||
|         $estimate->status = Estimate::STATUS_SENT; | ||||
|         $estimate->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function estimateToInvoice(Request $request, $id) | ||||
|     { | ||||
|         $estimate = Estimate::with(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes'])->find($id); | ||||
|         $invoice_date = Carbon::parse($estimate->estimate_date); | ||||
|         $due_date = Carbon::parse($estimate->estimate_date)->addDays(7); | ||||
|         $tax_per_item = CompanySetting::getSetting( | ||||
|                 'tax_per_item', | ||||
|                 $request->header('company') | ||||
|             ) ? CompanySetting::getSetting( | ||||
|                 'tax_per_item', | ||||
|                 $request->header('company') | ||||
|             ) : 'NO'; | ||||
|         $discount_per_item = CompanySetting::getSetting( | ||||
|                 'discount_per_item', | ||||
|                 $request->header('company') | ||||
|             ) ? CompanySetting::getSetting( | ||||
|                 'discount_per_item', | ||||
|                 $request->header('company') | ||||
|             ) : 'NO'; | ||||
|  | ||||
|         $invoice = Invoice::create([ | ||||
|             'invoice_date' => $invoice_date, | ||||
|             'due_date' => $due_date, | ||||
|             'invoice_number' => "INV-".Invoice::getNextInvoiceNumber(), | ||||
|             'reference_number' => $estimate->reference_number, | ||||
|             'user_id' => $estimate->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_template_id' => 1, | ||||
|             'status' => Invoice::STATUS_DRAFT, | ||||
|             'paid_status' => Invoice::STATUS_UNPAID, | ||||
|             'sub_total' => $estimate->sub_total, | ||||
|             'discount' => $estimate->discount, | ||||
|             'discount_type' => $estimate->discount_type, | ||||
|             'discount_val' => $estimate->discount_val, | ||||
|             'total' => $estimate->total, | ||||
|             'due_amount' => $estimate->total, | ||||
|             'tax_per_item' => $tax_per_item, | ||||
|             'discount_per_item' => $discount_per_item, | ||||
|             'tax' => $estimate->tax, | ||||
|             'notes' => $estimate->notes, | ||||
|             'unique_hash' => str_random(60) | ||||
|         ]); | ||||
|  | ||||
|         $invoiceItems = $estimate->items->toArray(); | ||||
|  | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $invoiceItem['name'] = $invoiceItem['name']; | ||||
|             $item = $invoice->items()->create($invoiceItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) { | ||||
|                 foreach ($invoiceItem['taxes'] as $tax) { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|  | ||||
|                     if ($tax['amount']) { | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($estimate->taxes) { | ||||
|             foreach ($estimate->taxes->toArray() as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|                 $invoice->taxes()->create($tax); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::with([ | ||||
|             'items', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes' | ||||
|         ])->find($invoice->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoice' => $invoice | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         foreach ($request->id as $id) { | ||||
|             Estimate::deleteEstimate($id); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,122 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Crater\ExpenseCategory; | ||||
| use Crater\Expense; | ||||
| use Crater\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Http\Requests\ExpenseCategoryRequest; | ||||
|  | ||||
| class ExpenseCategoryController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $categories = ExpenseCategory::whereCompany($request->header('company'))->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'categories' => $categories | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         // return view('app.categories.create'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(ExpenseCategoryRequest $request) | ||||
|     { | ||||
|         $category = new ExpenseCategory(); | ||||
|         $category->name = $request->name; | ||||
|         $category->description = $request->description; | ||||
|         $category->company_id = $request->header('company'); | ||||
|         $category->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\ExpenseCategory $ExpenseCategory | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(ExpenseCategory $ExpenseCategory) | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for editing the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\ExpensesCategory $ExpensesCategory | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function edit($id) | ||||
|     { | ||||
|         $category = ExpenseCategory::findOrFail($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'category' => $category | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Crater\ExpenseCategory $ExpenseCategory | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(ExpenseCategoryRequest $request, $id) | ||||
|     { | ||||
|         $category = ExpenseCategory::findOrFail($id); | ||||
|         $category->name = $request->name; | ||||
|         $category->description = $request->description; | ||||
|         $category->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\ExpensesCategory $expensesCategory | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy($id) | ||||
|     { | ||||
|         $category = ExpenseCategory::find($id); | ||||
|         if ($category->expenses() && $category->expenses()->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'success' => false | ||||
|             ]); | ||||
|         } | ||||
|         $category->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,260 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Crater\Expense; | ||||
| use Crater\User; | ||||
| use Crater\Currency; | ||||
| use Crater\Company; | ||||
| use Crater\CompanySetting; | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\ExpenseCategory; | ||||
| use Crater\Http\Requests\ExpenseRequest; | ||||
| use Carbon\Carbon; | ||||
| use Intervention\Image\Facades\Image; | ||||
|  | ||||
| class ExpensesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $expenses = Expense::with('category') | ||||
|             ->join('expense_categories', 'expense_categories.id', '=', 'expenses.expense_category_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'expense_category_id', | ||||
|                 'search', | ||||
|                 'from_date', | ||||
|                 'to_date', | ||||
|                 'orderByField', | ||||
|                 'orderBy' | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('expenses.*', 'expense_categories.name') | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expenses' => $expenses, | ||||
|             'currency' => Currency::findOrFail( | ||||
|                 CompanySetting::getSetting('currency', $request->header('company')) | ||||
|             ) | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function create(Request $request) | ||||
|     { | ||||
|         $categories = ExpenseCategory::whereCompany($request->header('company'))->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'categories' => $categories | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(ExpenseRequest $request) | ||||
|     { | ||||
|         $expense_date = Carbon::createFromFormat('d/m/Y', $request->expense_date); | ||||
|  | ||||
|         $expense = new Expense(); | ||||
|         $expense->notes = $request->notes; | ||||
|         $expense->expense_category_id = $request->expense_category_id; | ||||
|         $expense->amount = $request->amount; | ||||
|         $expense->company_id = $request->header('company'); | ||||
|         $expense->expense_date = $expense_date; | ||||
|         $expense->save(); | ||||
|  | ||||
|         if ($request->hasFile('attachment_receipt')) { | ||||
|             $expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local'); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Expense $expense | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(Expense $expense) | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for editing the specified resource. | ||||
|      * | ||||
|      * @param  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function edit(Request $request,$id) | ||||
|     { | ||||
|         $categories = ExpenseCategory::whereCompany($request->header('company'))->get(); | ||||
|         $customers = User::where('role', 'customer')->whereCompany($request->header('company'))->get(); | ||||
|         $expense = Expense::with('category')->where('id', $id)->first(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'categories' => $categories, | ||||
|             'customers' => $customers, | ||||
|             'expense' => $expense | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Crater\Expense $expense | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(ExpenseRequest $request, Expense $expense) | ||||
|     { | ||||
|         $expense_date = Carbon::createFromFormat('d/m/Y', $request->expense_date); | ||||
|  | ||||
|         $expense = Expense::findOrFail($expense->id); | ||||
|         $expense->notes = $request->notes; | ||||
|         $expense->expense_category_id = $request->expense_category_id; | ||||
|         $expense->amount = $request->amount; | ||||
|         $expense->expense_date = $expense_date; | ||||
|         $expense->save(); | ||||
|  | ||||
|         if ($request->hasFile('attachment_receipt')) { | ||||
|             $expense->clearMediaCollection('receipts'); | ||||
|             $expense->addMediaFromRequest('attachment_receipt')->toMediaCollection('receipts', 'local'); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\Expense $expense | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(Expense $expense) | ||||
|     { | ||||
|         $expense->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         Expense::destroy($request->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Upload the expense receipts to storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param   $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function uploadReceipts(Request $request, $id) | ||||
|     { | ||||
|         $data = json_decode($request->attachment_receipt); | ||||
|  | ||||
|         if($data) { | ||||
|             $expense = Expense::find($id); | ||||
|  | ||||
|             if($expense) { | ||||
|                 if($request->type === 'edit') { | ||||
|                     $expense->clearMediaCollection('receipts'); | ||||
|                 } | ||||
|  | ||||
|                 $expense->addMediaFromBase64($data->data) | ||||
|                     ->usingFileName($data->name) | ||||
|                     ->toMediaCollection('receipts', 'local'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => 'Expense receipts uploaded successfully' | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function showReceipt($id) | ||||
|     { | ||||
|         $expense = Expense::find($id); | ||||
|         $imagePath  = null; | ||||
|  | ||||
|         if($expense) { | ||||
|             $media = $expense->getFirstMedia('receipts'); | ||||
|             if($media) { | ||||
|                 $imagePath = $media->getPath(); | ||||
|             } else { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'receipt_does_not_exist' | ||||
|                 ]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $type = \File::mimeType($imagePath); | ||||
|  | ||||
|         $image = 'data:'.$type.';base64,'.base64_encode(file_get_contents($imagePath)); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'image' => $image, | ||||
|             'type' => $type | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function downloadReceipt($id, $hash) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $expense = Expense::whereCompany($company->id) | ||||
|             ->where('id', $id) | ||||
|             ->first(); | ||||
|         $imagePath  = null; | ||||
|  | ||||
|         if($expense) { | ||||
|             $media = $expense->getFirstMedia('receipts'); | ||||
|             if($media) { | ||||
|                 $imagePath = $media->getPath(); | ||||
|                 $filename = $media->getPath(); | ||||
|                 $type = \File::mimeType($imagePath); | ||||
|  | ||||
|                 $headers = array( | ||||
|                     'Content-Type' => $type, | ||||
|                 ); | ||||
|  | ||||
|                 $response = \Response::download($imagePath, $media->file_name); | ||||
|                 ob_end_clean(); | ||||
|                 return $response; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'error' => 'receipt_not_found' | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,374 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Invoice; | ||||
| use PDF; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Estimate; | ||||
| use Crater\User; | ||||
| use Crater\Company; | ||||
| use Crater\InvoiceTemplate; | ||||
| use Crater\EstimateTemplate; | ||||
| use Crater\Mail\EstimateViewed; | ||||
| use Crater\Mail\InvoiceViewed; | ||||
|  | ||||
| class FrontendController extends Controller | ||||
| { | ||||
|     public function home() | ||||
|     { | ||||
|         return view('front.index'); | ||||
|     } | ||||
|  | ||||
|     public function getCustomerEstimatePdf($id) | ||||
|     { | ||||
|         $estimate = Estimate::with( | ||||
|                 'user', | ||||
|                 'items', | ||||
|                 'user.billingAddress', | ||||
|                 'user.shippingAddress' | ||||
|             ) | ||||
|             ->where('unique_hash', $id) | ||||
|             ->first(); | ||||
|  | ||||
|         $taxTypes = []; | ||||
|         $taxes = []; | ||||
|         $labels = []; | ||||
|  | ||||
|         if ($estimate->tax_per_item === 'YES') { | ||||
|             foreach ($estimate->items as $item) { | ||||
|                 foreach ($item->taxes as $tax) { | ||||
|                     if (!in_array($tax->name, $taxTypes)) { | ||||
|                         array_push($taxTypes, $tax->name); | ||||
|                         array_push($labels, $tax->name.' ('.$tax->percent.'%)'); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             foreach ($taxTypes as $taxType) { | ||||
|                 $total = 0; | ||||
|  | ||||
|                 foreach ($estimate->items as $item) { | ||||
|                     foreach ($item->taxes as $tax) { | ||||
|                         if($tax->name == $taxType) { | ||||
|                             $total += $tax->amount; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 array_push($taxes, $total); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $estimateTemplate = EstimateTemplate::find($estimate->estimate_template_id); | ||||
|  | ||||
|         $company = Company::find($estimate->company_id); | ||||
|  | ||||
|         $logo = $company->getMedia('logo')->first(); | ||||
|  | ||||
|         if($logo) { | ||||
|             $logo = $logo->getFullUrl(); | ||||
|         } | ||||
|  | ||||
|         if ($estimate && ($estimate->status == Estimate::STATUS_SENT || $estimate->status == Estimate::STATUS_DRAFT)) { | ||||
|             $estimate->status = Estimate::STATUS_VIEWED; | ||||
|             $estimate->save(); | ||||
|             $notifyEstimateViewed = CompanySetting::getSetting( | ||||
|                 'notify_estimate_viewed', | ||||
|                 $estimate->company_id | ||||
|             ); | ||||
|  | ||||
|             if ($notifyEstimateViewed == 'YES') { | ||||
|                 $data['estimate'] = Estimate::findOrFail($estimate->id)->toArray(); | ||||
|                 $data['user'] = User::find($estimate->user_id)->toArray(); | ||||
|                 $notificationEmail = CompanySetting::getSetting( | ||||
|                     'notification_email', | ||||
|                     $estimate->company_id | ||||
|                 ); | ||||
|  | ||||
|                 \Mail::to($notificationEmail)->send(new EstimateViewed($data)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $companyAddress = User::with(['addresses', 'addresses.country'])->find(1); | ||||
|  | ||||
|         $colors = [ | ||||
|             'invoice_primary_color', | ||||
|             'invoice_column_heading', | ||||
|             'invoice_field_label', | ||||
|             'invoice_field_value', | ||||
|             'invoice_body_text', | ||||
|             'invoice_description_text', | ||||
|             'invoice_border_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($estimate->company_id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'estimate' => $estimate, | ||||
|             'logo' => $logo ?? null, | ||||
|             'company_address' => $companyAddress, | ||||
|             'colors' => $colorSettings, | ||||
|             'labels' => $labels, | ||||
|             'taxes' => $taxes | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.estimate.'.$estimateTemplate->view); | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function getCustomerInvoicePdf($id) | ||||
|     { | ||||
|         $invoice = Invoice::with([ | ||||
|                 'items', | ||||
|                 'items.taxes', | ||||
|                 'user', | ||||
|                 'invoiceTemplate', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->where('unique_hash', $id) | ||||
|             ->first(); | ||||
|  | ||||
|         $taxTypes = []; | ||||
|         $taxes = []; | ||||
|         $labels = []; | ||||
|  | ||||
|         if ($invoice->tax_per_item === 'YES') { | ||||
|             foreach ($invoice->items as $item) { | ||||
|                 foreach ($item->taxes as $tax) { | ||||
|                     if (!in_array($tax->name, $labels)) { | ||||
|                         array_push($taxTypes, $tax->name); | ||||
|                         array_push($labels, $tax->name.' ('.$tax->percent.'%)'); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             foreach ($taxTypes as $taxType) { | ||||
|                 $total = 0; | ||||
|  | ||||
|                 foreach ($invoice->items as $item) { | ||||
|                     foreach ($item->taxes as $tax) { | ||||
|                         if($tax->name == $taxType) { | ||||
|                             $total += $tax->amount; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 array_push($taxes, $total); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoiceTemplate = InvoiceTemplate::find($invoice->invoice_template_id); | ||||
|  | ||||
|         $company = Company::find($invoice->company_id); | ||||
|         $logo = $company->getMedia('logo')->first(); | ||||
|  | ||||
|         if($logo) { | ||||
|             $logo = $logo->getFullUrl(); | ||||
|         } | ||||
|  | ||||
|         if ($invoice && ($invoice->status == Invoice::STATUS_SENT || $invoice->status == Invoice::STATUS_DRAFT)) { | ||||
|             $invoice->status = Invoice::STATUS_VIEWED; | ||||
|             $invoice->viewed = true; | ||||
|             $invoice->save(); | ||||
|             $notifyInvoiceViewed = CompanySetting::getSetting( | ||||
|                 'notify_invoice_viewed', | ||||
|                 $invoice->company_id | ||||
|             ); | ||||
|  | ||||
|             if ($notifyInvoiceViewed == 'YES') { | ||||
|                 $data['invoice'] = Invoice::findOrFail($invoice->id)->toArray(); | ||||
|                 $data['user'] = User::find($invoice->user_id)->toArray(); | ||||
|                 $notificationEmail = CompanySetting::getSetting( | ||||
|                     'notification_email', | ||||
|                     $invoice->company_id | ||||
|                 ); | ||||
|  | ||||
|                 \Mail::to($notificationEmail)->send(new InvoiceViewed($data)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $companyAddress = User::with(['addresses', 'addresses.country'])->find(1); | ||||
|  | ||||
|         $colors = [ | ||||
|             'invoice_primary_color', | ||||
|             'invoice_column_heading', | ||||
|             'invoice_field_label', | ||||
|             'invoice_field_value', | ||||
|             'invoice_body_text', | ||||
|             'invoice_description_text', | ||||
|             'invoice_border_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($invoice->company_id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'invoice' => $invoice, | ||||
|             'colors' => $colorSettings, | ||||
|             'company_address' => $companyAddress, | ||||
|             'logo' => $logo ?? null, | ||||
|             'labels' => $labels, | ||||
|             'taxes' => $taxes | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.invoice.'.$invoiceTemplate->view); | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function getEstimatePdf($id) | ||||
|     { | ||||
|         $estimate = Estimate::with([ | ||||
|                 'items', | ||||
|                 'items.taxes', | ||||
|                 'user', | ||||
|                 'estimateTemplate', | ||||
|                 'taxes', | ||||
|                 'taxes.taxType' | ||||
|             ]) | ||||
|             ->where('unique_hash', $id) | ||||
|             ->first(); | ||||
|  | ||||
|         $taxTypes = []; | ||||
|         $taxes = []; | ||||
|         $labels = []; | ||||
|  | ||||
|         if ($estimate->tax_per_item === 'YES') { | ||||
|             foreach ($estimate->items as $item) { | ||||
|                 foreach ($item->taxes as $tax) { | ||||
|                     if (!in_array($tax->name, $taxTypes)) { | ||||
|                         array_push($taxTypes, $tax->name); | ||||
|                         array_push($labels, $tax->name.' ('.$tax->percent.'%)'); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             foreach ($taxTypes as $taxType) { | ||||
|                 $total = 0; | ||||
|  | ||||
|                 foreach ($estimate->items as $item) { | ||||
|                     foreach ($item->taxes as $tax) { | ||||
|                         if($tax->name == $taxType) { | ||||
|                             $total += $tax->amount; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 array_push($taxes, $total); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $estimateTemplate = EstimateTemplate::find($estimate->estimate_template_id); | ||||
|  | ||||
|         $company = Company::find($estimate->company_id); | ||||
|         $companyAddress = User::with(['addresses', 'addresses.country'])->find(1); | ||||
|         $logo = $company->getMedia('logo')->first(); | ||||
|  | ||||
|         if($logo) { | ||||
|             $logo = $logo->getFullUrl(); | ||||
|         } | ||||
|  | ||||
|         $colors = [ | ||||
|             'invoice_primary_color', | ||||
|             'invoice_column_heading', | ||||
|             'invoice_field_label', | ||||
|             'invoice_field_value', | ||||
|             'invoice_body_text', | ||||
|             'invoice_description_text', | ||||
|             'invoice_border_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($estimate->company_id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'estimate' => $estimate, | ||||
|             'logo' => $logo ?? null, | ||||
|             'company_address' => $companyAddress, | ||||
|             'colors' => $colorSettings, | ||||
|             'labels' => $labels, | ||||
|             'taxes' => $taxes | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.estimate.'.$estimateTemplate->view); | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function getInvoicePdf($id) | ||||
|     { | ||||
|         $invoice = Invoice::with([ | ||||
|                 'items', | ||||
|                 'items.taxes', | ||||
|                 'user', | ||||
|                 'invoiceTemplate', | ||||
|                 'taxes' | ||||
|             ]) | ||||
|             ->where('unique_hash', $id) | ||||
|             ->first(); | ||||
|  | ||||
|         $taxTypes = []; | ||||
|         $taxes = []; | ||||
|         $labels = []; | ||||
|  | ||||
|         if ($invoice->tax_per_item === 'YES') { | ||||
|             foreach ($invoice->items as $item) { | ||||
|                 foreach ($item->taxes as $tax) { | ||||
|                     if (!in_array($tax->name, $taxTypes)) { | ||||
|                         array_push($taxTypes, $tax->name); | ||||
|                         array_push($labels, $tax->name.' ('.$tax->percent.'%)'); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             foreach ($taxTypes as $taxType) { | ||||
|                 $total = 0; | ||||
|  | ||||
|                 foreach ($invoice->items as $item) { | ||||
|                     foreach ($item->taxes as $tax) { | ||||
|                         if($tax->name == $taxType) { | ||||
|                             $total += $tax->amount; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 array_push($taxes, $total); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoiceTemplate = InvoiceTemplate::find($invoice->invoice_template_id); | ||||
|         $company = Company::find($invoice->company_id); | ||||
|         $companyAddress = User::with(['addresses', 'addresses.country'])->find(1); | ||||
|  | ||||
|         $logo = $company->getMedia('logo')->first(); | ||||
|  | ||||
|         if($logo) { | ||||
|             $logo = $logo->getFullUrl(); | ||||
|         } | ||||
|  | ||||
|         $colors = [ | ||||
|             'invoice_primary_color', | ||||
|             'invoice_column_heading', | ||||
|             'invoice_field_label', | ||||
|             'invoice_field_value', | ||||
|             'invoice_body_text', | ||||
|             'invoice_description_text', | ||||
|             'invoice_border_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($invoice->company_id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'invoice' => $invoice, | ||||
|             'company_address' => $companyAddress, | ||||
|             'logo' => $logo ?? null, | ||||
|             'colors' => $colorSettings, | ||||
|             'labels' => $labels, | ||||
|             'taxes' => $taxes | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.invoice.'.$invoiceTemplate->view); | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
| } | ||||
| @ -1,470 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Company; | ||||
| use Illuminate\Support\Collection; | ||||
| use Crater\Currency; | ||||
| use Crater\InvoiceTemplate; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Invoice; | ||||
| use Crater\InvoiceItem; | ||||
| use Carbon\Carbon; | ||||
| use Crater\Item; | ||||
| use Crater\Mail\invoicePdf; | ||||
| use function MongoDB\BSON\toJSON; | ||||
| use Illuminate\Support\Facades\Log; | ||||
| use Crater\User; | ||||
| use Mailgun\Mailgun; | ||||
| use PDF; | ||||
| use Validator; | ||||
| use Crater\TaxType; | ||||
| use Crater\Tax; | ||||
|  | ||||
| class InvoicesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $invoices = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes']) | ||||
|             ->join('users', 'users.id', '=', 'invoices.user_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'status', | ||||
|                 'paid_status', | ||||
|                 'customer_id', | ||||
|                 'invoice_number', | ||||
|                 'from_date', | ||||
|                 'to_date', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|                 'search', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('invoices.*', 'users.name') | ||||
|             ->latest() | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoices' => $invoices, | ||||
|             'invoiceTotalCount' => Invoice::count() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function create(Request $request) | ||||
|     { | ||||
|         $tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company')); | ||||
|         $discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company')); | ||||
|         $invoice_prefix = CompanySetting::getSetting('invoice_prefix', $request->header('company')); | ||||
|         $invoice_num_auto_generate = CompanySetting::getSetting('invoice_auto_generate', $request->header('company')); | ||||
|  | ||||
|         $nextInvoiceNumberAttribute = null; | ||||
|         $nextInvoiceNumber = Invoice::getNextInvoiceNumber($invoice_prefix); | ||||
|  | ||||
|         if ($invoice_num_auto_generate == "YES") { | ||||
|             $nextInvoiceNumberAttribute = $nextInvoiceNumber; | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'nextInvoiceNumberAttribute' => $nextInvoiceNumberAttribute, | ||||
|             'nextInvoiceNumber' => $invoice_prefix.'-'.$nextInvoiceNumber, | ||||
|             'items' => Item::with('taxes')->whereCompany($request->header('company'))->get(), | ||||
|             'invoiceTemplates' => InvoiceTemplate::all(), | ||||
|             'tax_per_item' => $tax_per_item, | ||||
|             'discount_per_item' => $discount_per_item, | ||||
|             'invoice_prefix' => $invoice_prefix | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(Requests\InvoicesRequest $request) | ||||
|     { | ||||
|         $invoice_number = explode("-",$request->invoice_number); | ||||
|         $number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1])); | ||||
|  | ||||
|         Validator::make($number_attributes, [ | ||||
|             'invoice_number' => 'required|unique:invoices,invoice_number' | ||||
|         ])->validate(); | ||||
|  | ||||
|         $invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date); | ||||
|         $due_date = Carbon::createFromFormat('d/m/Y', $request->due_date); | ||||
|         $status = Invoice::STATUS_DRAFT; | ||||
|  | ||||
|         $tax_per_item = CompanySetting::getSetting('tax_per_item', $request->header('company')) ?? 'NO'; | ||||
|         $discount_per_item = CompanySetting::getSetting('discount_per_item', $request->header('company')) ?? 'NO'; | ||||
|  | ||||
|         if ($request->has('invoiceSend')) { | ||||
|             $status = Invoice::STATUS_SENT; | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::create([ | ||||
|             'invoice_date' => $invoice_date, | ||||
|             'due_date' => $due_date, | ||||
|             'invoice_number' => $number_attributes['invoice_number'], | ||||
|             'reference_number' => $request->reference_number, | ||||
|             'user_id' => $request->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_template_id' => $request->invoice_template_id, | ||||
|             'status' => $status, | ||||
|             'paid_status' => Invoice::STATUS_UNPAID, | ||||
|             'sub_total' => $request->sub_total, | ||||
|             'discount' => $request->discount, | ||||
|             'discount_type' => $request->discount_type, | ||||
|             'discount_val' => $request->discount_val, | ||||
|             'total' => $request->total, | ||||
|             'due_amount' => $request->total, | ||||
|             'tax_per_item' => $tax_per_item, | ||||
|             'discount_per_item' => $discount_per_item, | ||||
|             'tax' => $request->tax, | ||||
|             'notes' => $request->notes, | ||||
|             'unique_hash' => str_random(60) | ||||
|         ]); | ||||
|  | ||||
|         $invoiceItems = $request->items; | ||||
|  | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $item = $invoice->items()->create($invoiceItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) { | ||||
|                 foreach ($invoiceItem['taxes'] as $tax) { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|                     if (gettype($tax['amount']) !== "NULL") { | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('taxes')) { | ||||
|             foreach ($request->taxes as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|  | ||||
|                 if (gettype($tax['amount']) !== "NULL") { | ||||
|                     $invoice->taxes()->create($tax); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('invoiceSend')) { | ||||
|             $data['invoice'] = Invoice::findOrFail($invoice->id)->toArray(); | ||||
|             $data['user'] = User::find($request->user_id)->toArray(); | ||||
|             $data['company'] = Company::find($invoice->company_id); | ||||
|  | ||||
|             $notificationEmail = CompanySetting::getSetting( | ||||
|                 'notification_email', | ||||
|                 $request->header('company') | ||||
|             ); | ||||
|  | ||||
|             $email = $data['user']['email']; | ||||
|  | ||||
|             if (!$email) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'user_email_does_not_exist' | ||||
|                 ]); | ||||
|             } | ||||
|  | ||||
|             if (!$notificationEmail) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'notification_email_does_not_exist' | ||||
|                 ]); | ||||
|             } | ||||
|  | ||||
|             \Mail::to($email)->send(new invoicePdf($data, $notificationEmail)); | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'url' => url('/invoices/pdf/'.$invoice->unique_hash), | ||||
|             'invoice' => $invoice | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  int $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(Request $request, $id) | ||||
|     { | ||||
|         $invoice = Invoice::with([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes.taxType' | ||||
|         ])->find($id); | ||||
|  | ||||
|         $siteData = [ | ||||
|             'invoice' => $invoice, | ||||
|             'shareable_link' => url('/invoices/pdf/' . $invoice->unique_hash) | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($siteData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for editing the specified resource. | ||||
|      * | ||||
|      * @param  int $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function edit(Request $request,$id) | ||||
|     { | ||||
|         $invoice = Invoice::with([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes.taxType' | ||||
|         ])->find($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'nextInvoiceNumber' => $invoice->getInvoiceNumAttribute(), | ||||
|             'invoice' => $invoice, | ||||
|             'invoiceTemplates' => InvoiceTemplate::all(), | ||||
|             'tax_per_item' => $invoice->tax_per_item, | ||||
|             'discount_per_item' => $invoice->discount_per_item, | ||||
|             'shareable_link' => url('/invoices/pdf/'.$invoice->unique_hash), | ||||
|             'invoice_prefix' => $invoice->getInvoicePrefixAttribute() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  int $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(Requests\InvoicesRequest $request, $id) | ||||
|     { | ||||
|         $invoice_number = explode("-",$request->invoice_number); | ||||
|         $number_attributes['invoice_number'] = $invoice_number[0].'-'.sprintf('%06d', intval($invoice_number[1])); | ||||
|  | ||||
|         Validator::make($number_attributes, [ | ||||
|             'invoice_number' => 'required|unique:invoices,invoice_number'.','.$id | ||||
|         ])->validate(); | ||||
|  | ||||
|         $invoice_date = Carbon::createFromFormat('d/m/Y', $request->invoice_date); | ||||
|         $due_date = Carbon::createFromFormat('d/m/Y', $request->due_date); | ||||
|  | ||||
|         $invoice = Invoice::find($id); | ||||
|         $oldAmount = $invoice->total; | ||||
|  | ||||
|         if ($oldAmount != $request->total) { | ||||
|             $oldAmount = (int)round($request->total) - (int)$oldAmount; | ||||
|         } else { | ||||
|             $oldAmount = 0; | ||||
|         } | ||||
|  | ||||
|         $invoice->due_amount = ($invoice->due_amount + $oldAmount); | ||||
|  | ||||
|         if ($invoice->due_amount == 0 && $invoice->paid_status != Invoice::STATUS_PAID) { | ||||
|             $invoice->status = Invoice::STATUS_COMPLETED; | ||||
|             $invoice->paid_status = Invoice::STATUS_PAID; | ||||
|         } elseif ($invoice->due_amount < 0 && $invoice->paid_status != Invoice::STATUS_UNPAID) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'invalid_due_amount' | ||||
|             ]); | ||||
|         } elseif ($invoice->due_amount != 0 && $invoice->paid_status == Invoice::STATUS_PAID) { | ||||
|             $invoice->status = $invoice->getPreviousStatus(); | ||||
|             $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|         } | ||||
|  | ||||
|         $invoice->invoice_date = $invoice_date; | ||||
|         $invoice->due_date = $due_date; | ||||
|         $invoice->invoice_number =  $number_attributes['invoice_number']; | ||||
|         $invoice->reference_number = $request->reference_number; | ||||
|         $invoice->user_id = $request->user_id; | ||||
|         $invoice->invoice_template_id = $request->invoice_template_id; | ||||
|         $invoice->sub_total = $request->sub_total; | ||||
|         $invoice->total = $request->total; | ||||
|         $invoice->discount = $request->discount; | ||||
|         $invoice->discount_type = $request->discount_type; | ||||
|         $invoice->discount_val = $request->discount_val; | ||||
|         $invoice->tax = $request->tax; | ||||
|         $invoice->notes = $request->notes; | ||||
|         $invoice->save(); | ||||
|  | ||||
|         $oldItems = $invoice->items->toArray(); | ||||
|         $oldTaxes = $invoice->taxes->toArray(); | ||||
|         $invoiceItems = $request->items; | ||||
|  | ||||
|         foreach ($oldItems as $oldItem) { | ||||
|             InvoiceItem::destroy($oldItem['id']); | ||||
|         } | ||||
|  | ||||
|         foreach ($oldTaxes as $oldTax) { | ||||
|             Tax::destroy($oldTax['id']); | ||||
|         } | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $item = $invoice->items()->create($invoiceItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) { | ||||
|                 foreach ($invoiceItem['taxes'] as $tax) { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|                     if (gettype($tax['amount']) !== "NULL") { | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($request->has('taxes')) { | ||||
|             foreach ($request->taxes as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|  | ||||
|                 if (gettype($tax['amount']) !== "NULL") { | ||||
|                     $invoice->taxes()->create($tax); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::with(['items', 'user', 'invoiceTemplate', 'taxes'])->find($invoice->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'url' => url('/invoices/pdf/' . $invoice->unique_hash), | ||||
|             'invoice' => $invoice, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  int $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy($id) | ||||
|     { | ||||
|         $invoice = Invoice::find($id); | ||||
|  | ||||
|         if ($invoice->payments()->exists() && $invoice->payments()->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'payment_attached' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::destroy($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         foreach ($request->id as $id) { | ||||
|             $invoice = Invoice::find($id); | ||||
|  | ||||
|             if ($invoice->payments()->exists() && $invoice->payments()->count() > 0) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'payment_attached' | ||||
|                 ]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::destroy($request->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function sendInvoice(Request $request) | ||||
|     { | ||||
|         $invoice = Invoice::findOrFail($request->id); | ||||
|  | ||||
|         $data['invoice'] = $invoice->toArray(); | ||||
|         $userId = $data['invoice']['user_id']; | ||||
|         $data['user'] = User::find($userId)->toArray(); | ||||
|         $data['company'] = Company::find($invoice->company_id); | ||||
|         $email = $data['user']['email']; | ||||
|         $notificationEmail = CompanySetting::getSetting( | ||||
|             'notification_email', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         if (!$email) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'user_email_does_not_exist' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         if (!$notificationEmail) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'notification_email_does_not_exist' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         \Mail::to($email)->send(new invoicePdf($data, $notificationEmail)); | ||||
|  | ||||
|         if ($invoice->status == Invoice::STATUS_DRAFT) { | ||||
|             $invoice->status = Invoice::STATUS_SENT; | ||||
|             $invoice->sent = true; | ||||
|             $invoice->save(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function markAsSent(Request $request) | ||||
|     { | ||||
|         $invoice = Invoice::findOrFail($request->id); | ||||
|         $invoice->status = Invoice::STATUS_SENT; | ||||
|         $invoice->sent = true; | ||||
|         $invoice->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function markAsPaid(Request $request) | ||||
|     { | ||||
|         $invoice = Invoice::findOrFail($request->id); | ||||
|         $invoice->status = Invoice::STATUS_COMPLETED; | ||||
|         $invoice->paid_status = Invoice::STATUS_PAID; | ||||
|         $invoice->due_amount = 0; | ||||
|         $invoice->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getCustomersUnpaidInvoices(Request $request, $id) | ||||
|     { | ||||
|         $invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID) | ||||
|             ->where('user_id', $id)->where('due_amount', '>', 0) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoices' => $invoices | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,134 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Item; | ||||
| use Crater\TaxType; | ||||
| use Crater\Tax; | ||||
| use Crater\User; | ||||
|  | ||||
| class ItemsController extends Controller | ||||
| { | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $items = Item::applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'price', | ||||
|                 'unit', | ||||
|                 'orderByField', | ||||
|                 'orderBy' | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->latest() | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'items' => $items, | ||||
|             'taxTypes' => TaxType::latest()->get() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function edit(Request $request, $id) | ||||
|     { | ||||
|         $item = Item::with('taxes')->find($id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|             'taxes' => Tax::whereCompany($request->header('company')) | ||||
|                 ->latest() | ||||
|                 ->get() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function store(Requests\ItemsRequest $request) | ||||
|     { | ||||
|         $item = new Item(); | ||||
|         $item->name = $request->name; | ||||
|         $item->unit = $request->unit; | ||||
|         $item->description = $request->description; | ||||
|         $item->company_id = $request->header('company'); | ||||
|         $item->price = $request->price; | ||||
|         $item->save(); | ||||
|  | ||||
|         if ($request->has('taxes')) { | ||||
|             foreach ($request->taxes as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|                 $item->taxes()->create($tax); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $item = Item::with('taxes')->find($item->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'item' => $item | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function update(Requests\ItemsRequest $request, $id) | ||||
|     { | ||||
|         $item = Item::find($id); | ||||
|         $item->name = $request->name; | ||||
|         $item->unit = $request->unit; | ||||
|         $item->description = $request->description; | ||||
|         $item->price = $request->price; | ||||
|         $item->save(); | ||||
|  | ||||
|         $oldTaxes = $item->taxes->toArray(); | ||||
|  | ||||
|         foreach ($oldTaxes as $oldTax) { | ||||
|             Tax::destroy($oldTax['id']); | ||||
|         } | ||||
|  | ||||
|         if ($request->has('taxes')) { | ||||
|             foreach ($request->taxes as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|                 $item->taxes()->create($tax); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $item = Item::with('taxes')->find($item->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'item' => $item | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function destroy($id) | ||||
|     { | ||||
|         $data = Item::deleteItem($id); | ||||
|  | ||||
|         if (!$data) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'item_attached' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => $data | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         $items = []; | ||||
|         foreach ($request->id as $id) { | ||||
|             $item = Item::deleteItem($id); | ||||
|             if (!$item) { | ||||
|                 array_push($items, $id); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (empty($items)) { | ||||
|             return response()->json([ | ||||
|                 'success' => true | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'items' => $items | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,15 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Country; | ||||
|  | ||||
| class LocationController extends Controller | ||||
| { | ||||
|     public function getCountries() | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'countries' => Country::all() | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,295 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\User; | ||||
| use Crater\Company; | ||||
| use Crater\Address; | ||||
| use Crater\Http\Requests\ProfileRequest; | ||||
| use Crater\Http\Requests\CompanyRequest; | ||||
| use Crater\Http\Requests\CompanySettingRequest; | ||||
| use Crater\Space\DateFormatter; | ||||
| use Crater\Space\TimeZones; | ||||
| use Crater\Currency; | ||||
| use Crater\Setting; | ||||
| use Crater\CompanySetting; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
|  | ||||
| class OnboardingController extends Controller | ||||
| { | ||||
|     public function getOnboardingData(Request $request) | ||||
|     { | ||||
|         if (!\Storage::disk('local')->has('database_created')) { | ||||
|             return response()->json([ | ||||
|                 'profile_complete' => '0' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|  | ||||
|         if ($setting !== 'COMPLETED' && $setting < 4){ | ||||
|             return response()->json([ | ||||
|                 'profile_complete' => $setting | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $date_formats = DateFormatter::get_list(); | ||||
|         $time_zones = TimeZones::get_list(); | ||||
|         $languages = [ | ||||
|             ["code"=>"en", "name" => "English"], | ||||
|             ["code"=>"fr", "name" => "French"], | ||||
|             ["code"=>"es", "name" => "Spanish"] | ||||
|         ]; | ||||
|         $fiscal_years = [ | ||||
|             ['key' => 'january-december' , 'value' => '1-12'], | ||||
|             ['key' => 'february-january' , 'value' => '2-1'], | ||||
|             ['key' => 'march-february'   , 'value' => '3-2'], | ||||
|             ['key' => 'april-march'      , 'value' => '4-3'], | ||||
|             ['key' => 'may-april'        , 'value' => '5-4'], | ||||
|             ['key' => 'june-may'         , 'value' => '6-5'], | ||||
|             ['key' => 'july-june'        , 'value' => '7-6'], | ||||
|             ['key' => 'august-july'      , 'value' => '8-7'], | ||||
|             ['key' => 'september-august' , 'value' => '9-8'], | ||||
|             ['key' => 'october-september', 'value' => '10-9'], | ||||
|             ['key' => 'november-october' , 'value' => '11-10'], | ||||
|             ['key' => 'december-november', 'value' => '12-11'], | ||||
|         ]; | ||||
|         $user = User::with([ | ||||
|             'addresses', | ||||
|             'addresses.country', | ||||
|             'company' | ||||
|         ])->find(1); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'profile_complete' => $setting, | ||||
|             'languages' => $languages, | ||||
|             'date_formats' => $date_formats, | ||||
|             'time_zones' => $time_zones, | ||||
|             'fiscal_years' => $fiscal_years, | ||||
|             'currencies' => Currency::all() | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function adminProfile(ProfileRequest $request) | ||||
|     { | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|  | ||||
|         if ($setting == '1' || $setting == 'COMPLETED') { | ||||
|             return response()->json(['error' => 'Profile already created.']); | ||||
|         } else { | ||||
|             Setting::setSetting('profile_complete', 5); | ||||
|         } | ||||
|  | ||||
|         $user = User::find(1); | ||||
|         $user->name = $request->name; | ||||
|         $user->email = $request->email; | ||||
|  | ||||
|         if ($request->has('password')) { | ||||
|             $user->password = bcrypt($request->password); | ||||
|         } | ||||
|  | ||||
|         $user->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function uploadAdminAvatar(Request $request) | ||||
|     { | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|  | ||||
|         if ($setting == '1' || $setting == 'COMPLETED') { | ||||
|             return response()->json(['error' => 'Profile already created.']); | ||||
|         } | ||||
|         $data = json_decode($request->admin_avatar); | ||||
|  | ||||
|         if($data) { | ||||
|             $user = User::find($data->id); | ||||
|             if($user) { | ||||
|                 $user->clearMediaCollection('admin_avatar'); | ||||
|  | ||||
|                 $user->addMediaFromBase64($data->data) | ||||
|                     ->usingFileName($data->name) | ||||
|                     ->toMediaCollection('admin_avatar'); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function adminCompany(CompanyRequest $request) | ||||
|     { | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|  | ||||
|         if ($setting == '6' || $setting == 'COMPLETED') { | ||||
|             return response()->json(['error' => 'Company already created.']); | ||||
|         } else { | ||||
|             Setting::setSetting('profile_complete', 6); | ||||
|         } | ||||
|  | ||||
|         $user = User::find(1); | ||||
|         $company = $user->company; | ||||
|  | ||||
|         if (!$company) { | ||||
|             $company = new Company(); | ||||
|         } | ||||
|  | ||||
|         $company->name = $request->name; | ||||
|         $company->unique_hash = str_random(60); | ||||
|         $company->save(); | ||||
|         $user->company()->associate($company); | ||||
|         $user->save(); | ||||
|  | ||||
|         if ($request->has('logo') && $request->logo !== null && $request->logo !== 'undefined' ) { | ||||
|             $company->addMediaFromRequest('logo')->toMediaCollection('logo'); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $fields = $request->only([ | ||||
|             'address_street_1', | ||||
|             'address_street_2', | ||||
|             'city', | ||||
|             'state', | ||||
|             'country_id', | ||||
|             'zip', | ||||
|             'phone' | ||||
|         ]); | ||||
|         $address = Address::updateOrCreate(['user_id' => 1], $fields); | ||||
|         $user = User::with('addresses', 'company')->find(1); | ||||
|  | ||||
|         CompanySetting::setSetting( | ||||
|             'notification_email', | ||||
|             $user->email, | ||||
|             $company->id | ||||
|         ); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function companySettings(CompanySettingRequest $request) | ||||
|     { | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|  | ||||
|         if($setting == 'COMPLETED') { | ||||
|             return response()->json(['error' => 'Settings already saved.']); | ||||
|         } else { | ||||
|             Setting::setSetting('profile_complete', 'COMPLETED'); | ||||
|         } | ||||
|  | ||||
|         $user = User::find(1); | ||||
|  | ||||
|         $sets = ['currency', | ||||
|             'time_zone', | ||||
|             'language', | ||||
|             'carbon_date_format', | ||||
|             'moment_date_format', | ||||
|             'fiscal_year' | ||||
|         ]; | ||||
|  | ||||
|         foreach ($sets as $key) { | ||||
|             CompanySetting::setSetting( | ||||
|                 $key, | ||||
|                 $request->$key, | ||||
|                 $user->company_id | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $invoices = [ | ||||
|             'invoice_auto_generate' => 'YES', | ||||
|             'invoice_prefix' => 'INV' | ||||
|         ]; | ||||
|  | ||||
|         foreach ($invoices as $key => $value) { | ||||
|             CompanySetting::setSetting( | ||||
|                 $key, | ||||
|                 $value, | ||||
|                 $user->company_id | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $estimates = [ | ||||
|             'estimate_prefix' => 'EST', | ||||
|             'estimate_auto_generate' => 'YES' | ||||
|         ]; | ||||
|  | ||||
|         foreach ($estimates as $key => $value) { | ||||
|             CompanySetting::setSetting( | ||||
|                 $key, | ||||
|                 $value, | ||||
|                 $user->company_id | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $payments = [ | ||||
|             'payment_prefix' => 'PAY', | ||||
|             'payment_auto_generate' => 'YES' | ||||
|         ]; | ||||
|  | ||||
|         foreach ($payments as $key => $value) { | ||||
|             CompanySetting::setSetting( | ||||
|                 $key, | ||||
|                 $value, | ||||
|                 $user->company_id | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color' => '#5851D8', | ||||
|             'heading_text_color' => '#595959', | ||||
|             'section_heading_text_color' => '#040405', | ||||
|             'border_color' => '#EAF1FB', | ||||
|             'body_text_color' => '#595959', | ||||
|             'footer_text_color' => '#595959', | ||||
|             'footer_total_color' => '#5851D8', | ||||
|             'footer_bg_color' => '#F9FBFF', | ||||
|             'date_text_color' => '#A5ACC1', | ||||
|             'invoice_primary_color' => '#5851D8', | ||||
|             'invoice_column_heading' => '#55547A', | ||||
|             'invoice_field_label' => '#55547A', | ||||
|             'invoice_field_value' => '#040405', | ||||
|             'invoice_body_text' => '#040405', | ||||
|             'invoice_description_text' => '#595959', | ||||
|             'invoice_border_color' => '#EAF1FB' | ||||
|         ]; | ||||
|         foreach ($colors as $key => $value) { | ||||
|             CompanySetting::setSetting( | ||||
|                 $key, | ||||
|                 $value, | ||||
|                 $user->company_id | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         Setting::setSetting('version', config('crater.version')); | ||||
|  | ||||
|         Artisan::call('passport:install --force'); | ||||
|  | ||||
|         $client = DB::table('oauth_clients')->find(2); | ||||
|  | ||||
|         $path = base_path('.env'); | ||||
|  | ||||
|         if (file_exists($path)) { | ||||
|             file_put_contents($path, str_replace( | ||||
|                 'PROXY_OAUTH_CLIENT_SECRET='.config('auth.proxy.client_secret'), | ||||
|                 'PROXY_OAUTH_CLIENT_SECRET='.$client->secret, | ||||
|                 file_get_contents($path) | ||||
|             )); | ||||
|             file_put_contents($path, str_replace( | ||||
|                 'APP_DEBUG=true', | ||||
|                 'APP_DEBUG=false', | ||||
|                 file_get_contents($path) | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         $data['token'] = $user->createToken('password')->accessToken; | ||||
|  | ||||
|         return response()->json($data); | ||||
|     } | ||||
| } | ||||
| @ -1,279 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Currency; | ||||
| use Crater\Invoice; | ||||
| use Crater\Payment; | ||||
| use Carbon\Carbon; | ||||
| use function MongoDB\BSON\toJSON; | ||||
| use Crater\User; | ||||
| use Crater\Http\Requests\PaymentRequest; | ||||
| use Validator; | ||||
|  | ||||
| class PaymentController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $payments = Payment::with('user', 'invoice') | ||||
|             ->join('users', 'users.id', '=', 'payments.user_id') | ||||
|             ->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'payment_number', | ||||
|                 'payment_mode', | ||||
|                 'customer_id', | ||||
|                 'orderByField', | ||||
|                 'orderBy' | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('payments.*', 'users.name', 'invoices.invoice_number') | ||||
|             ->latest() | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'payments' => $payments | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function create(Request $request) | ||||
|     { | ||||
|         $payment_prefix = CompanySetting::getSetting('payment_prefix', $request->header('company')); | ||||
|         $payment_num_auto_generate = CompanySetting::getSetting('payment_auto_generate', $request->header('company')); | ||||
|  | ||||
|  | ||||
|         $nextPaymentNumberAttribute = null; | ||||
|         $nextPaymentNumber = Payment::getNextPaymentNumber($payment_prefix); | ||||
|  | ||||
|         if ($payment_num_auto_generate == "YES") { | ||||
|             $nextPaymentNumberAttribute = $nextPaymentNumber; | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customers' => User::where('role', 'customer') | ||||
|                 ->whereCompany($request->header('company')) | ||||
|                 ->get(), | ||||
|             'nextPaymentNumberAttribute' => $nextPaymentNumberAttribute, | ||||
|             'nextPaymentNumber' => $payment_prefix.'-'.$nextPaymentNumber, | ||||
|             'payment_prefix' => $payment_prefix | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(PaymentRequest $request) | ||||
|     { | ||||
|         $payment_number = explode("-",$request->payment_number); | ||||
|         $number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1])); | ||||
|  | ||||
|         Validator::make($number_attributes, [ | ||||
|             'payment_number' => 'required|unique:payments,payment_number' | ||||
|         ])->validate(); | ||||
|  | ||||
|         $payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date); | ||||
|  | ||||
|         if ($request->has('invoice_id') && $request->invoice_id != null) { | ||||
|             $invoice = Invoice::find($request->invoice_id); | ||||
|             if ($invoice && $invoice->due_amount == $request->amount) { | ||||
|                 $invoice->status = Invoice::STATUS_COMPLETED; | ||||
|                 $invoice->paid_status = Invoice::STATUS_PAID; | ||||
|                 $invoice->due_amount = 0; | ||||
|             } elseif ($invoice && $invoice->due_amount != $request->amount) { | ||||
|                 $invoice->due_amount = (int)$invoice->due_amount - (int)$request->amount; | ||||
|                 if ($invoice->due_amount < 0) { | ||||
|                     return response()->json([ | ||||
|                         'error' => 'invalid_amount' | ||||
|                     ]); | ||||
|                 } | ||||
|                 $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|             } | ||||
|             $invoice->save(); | ||||
|         } | ||||
|  | ||||
|         $payment = Payment::create([ | ||||
|             'payment_date' => $payment_date, | ||||
|             'payment_number' => $number_attributes['payment_number'], | ||||
|             'user_id' => $request->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_id' => $request->invoice_id, | ||||
|             'payment_mode' => $request->payment_mode, | ||||
|             'amount' => $request->amount, | ||||
|             'notes' => $request->notes, | ||||
|         ]); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'payment' => $payment, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show($id) | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for editing the specified resource. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function edit(Request $request, $id) | ||||
|     { | ||||
|         $payment = Payment::with('user', 'invoice')->find($id); | ||||
|  | ||||
|         $invoices = Invoice::where('paid_status', '<>', Invoice::STATUS_PAID) | ||||
|             ->where('user_id', $payment->user_id)->where('due_amount', '>', 0) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customers' => User::where('role', 'customer') | ||||
|                 ->whereCompany($request->header('company')) | ||||
|                 ->get(), | ||||
|             'nextPaymentNumber' => $payment->getPaymentNumAttribute(), | ||||
|             'payment_prefix' => $payment->getPaymentPrefixAttribute(), | ||||
|             'payment' => $payment, | ||||
|             'invoices' => $invoices | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(PaymentRequest $request, $id) | ||||
|     { | ||||
|         $payment_number = explode("-",$request->payment_number); | ||||
|         $number_attributes['payment_number'] = $payment_number[0].'-'.sprintf('%06d', intval($payment_number[1])); | ||||
|  | ||||
|         Validator::make($number_attributes, [ | ||||
|             'payment_number' => 'required|unique:payments,payment_number'.','.$id | ||||
|         ])->validate(); | ||||
|  | ||||
|         $payment_date = Carbon::createFromFormat('d/m/Y', $request->payment_date); | ||||
|  | ||||
|         $payment = Payment::find($id); | ||||
|         $oldAmount = $payment->amount; | ||||
|  | ||||
|         if ($request->has('invoice_id') && $request->invoice_id && ($oldAmount != $request->amount)) { | ||||
|             $amount = (int)$request->amount - (int)$oldAmount; | ||||
|             $invoice = Invoice::find($request->invoice_id); | ||||
|             $invoice->due_amount = (int)$invoice->due_amount - (int)$amount; | ||||
|  | ||||
|             if ($invoice->due_amount < 0) { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'invalid_amount' | ||||
|                 ]); | ||||
|             } | ||||
|  | ||||
|             if ($invoice->due_amount == 0) { | ||||
|                 $invoice->status = Invoice::STATUS_COMPLETED; | ||||
|                 $invoice->paid_status = Invoice::STATUS_PAID; | ||||
|             } else { | ||||
|                 $invoice->status = $invoice->getPreviousStatus(); | ||||
|                 $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|             } | ||||
|  | ||||
|             $invoice->save(); | ||||
|         } | ||||
|  | ||||
|         $payment->payment_date = $payment_date; | ||||
|         $payment->payment_number = $number_attributes['payment_number']; | ||||
|         $payment->user_id = $request->user_id; | ||||
|         $payment->invoice_id = $request->invoice_id; | ||||
|         $payment->payment_mode = $request->payment_mode; | ||||
|         $payment->amount = $request->amount; | ||||
|         $payment->notes = $request->notes; | ||||
|         $payment->save(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'payment' => $payment, | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy($id) | ||||
|     { | ||||
|         $payment = Payment::find($id); | ||||
|  | ||||
|         if ($payment->invoice_id != null) { | ||||
|             $invoice = Invoice::find($payment->invoice_id); | ||||
|             $invoice->due_amount = ((int)$invoice->due_amount + (int)$payment->amount); | ||||
|  | ||||
|             if ($invoice->due_amount == $invoice->total) { | ||||
|                 $invoice->paid_status = Invoice::STATUS_UNPAID; | ||||
|             } else { | ||||
|                 $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|             } | ||||
|  | ||||
|             $invoice->status = $invoice->getPreviousStatus(); | ||||
|             $invoice->save(); | ||||
|         } | ||||
|  | ||||
|         $payment->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         foreach ($request->id as $id) { | ||||
|             $payment = Payment::find($id); | ||||
|  | ||||
|             if ($payment->invoice_id != null) { | ||||
|                 $invoice = Invoice::find($payment->invoice_id); | ||||
|                 $invoice->due_amount = ((int)$invoice->due_amount + (int)$payment->amount); | ||||
|  | ||||
|                 if ($invoice->due_amount == $invoice->total) { | ||||
|                     $invoice->paid_status = Invoice::STATUS_UNPAID; | ||||
|                 } else { | ||||
|                     $invoice->paid_status = Invoice::STATUS_PARTIALLY_PAID; | ||||
|                 } | ||||
|  | ||||
|                 $invoice->status = $invoice->getPreviousStatus(); | ||||
|                 $invoice->save(); | ||||
|             } | ||||
|  | ||||
|             $payment->delete(); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,293 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\User; | ||||
| use Crater\Invoice; | ||||
| use Crater\Company; | ||||
| use Crater\InvoiceItem; | ||||
| use Crater\Expense; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Tax; | ||||
| use PDF; | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
|  | ||||
| class ReportController extends Controller | ||||
| { | ||||
|     public function customersSalesReport($hash, Request $request) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $start = Carbon::createFromFormat('d/m/Y', $request->from_date); | ||||
|         $end = Carbon::createFromFormat('d/m/Y', $request->to_date); | ||||
|  | ||||
|         $customers = User::with(['invoices' => function ($query) use ($start, $end) { | ||||
|                 $query->whereBetween( | ||||
|                     'invoice_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ); | ||||
|             }]) | ||||
|             ->customer() | ||||
|             ->whereCompany($company->id) | ||||
|             ->applyInvoiceFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($customers as $customer) { | ||||
|             $customerTotalAmount = 0; | ||||
|             foreach ($customer->invoices as $invoice) { | ||||
|                 $customerTotalAmount += $invoice->total; | ||||
|             } | ||||
|             $customer->totalAmount = $customerTotalAmount; | ||||
|             $totalAmount += $customerTotalAmount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'customers' => $customers, | ||||
|             'totalAmount' => $totalAmount, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.sales-customers'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function itemsSalesReport($hash, Request $request) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $items = InvoiceItem::whereCompany($company->id) | ||||
|             ->applyInvoiceFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->itemAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($items as $item) { | ||||
|             $totalAmount += $item->total_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'items' => $items, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'totalAmount' => $totalAmount, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.sales-items'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function expensesReport($hash, Request $request) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $expenseCategories = Expense::with('category') | ||||
|             ->whereCompany($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($expenseCategories as $category) { | ||||
|             $totalAmount += $category->total_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'expenseCategories' => $expenseCategories, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'totalExpense' => $totalAmount, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.expenses'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function taxSummery($hash, Request $request) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $taxTypes = Tax::with('taxType', 'invoice', 'invoiceItem') | ||||
|             ->whereCompany($company->id) | ||||
|             ->whereInvoicesFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->taxAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($taxTypes as $taxType) { | ||||
|             $totalAmount += $taxType->total_tax_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color' | ||||
|         ]; | ||||
|  | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'taxTypes' => $taxTypes, | ||||
|             'totalTaxAmount' => $totalAmount, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date | ||||
|         ]); | ||||
|  | ||||
|         $pdf = PDF::loadView('app.pdf.reports.tax-summary'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
|  | ||||
|     public function profitLossReport($hash, Request $request) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $invoicesAmount = Invoice::whereCompany($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->wherePaidStatus(Invoice::STATUS_PAID) | ||||
|             ->sum('total'); | ||||
|  | ||||
|         $expenseCategories = Expense::with('category') | ||||
|             ->whereCompany($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($expenseCategories as $category) { | ||||
|             $totalAmount += $category->total_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('d/m/Y', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('d/m/Y', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color' | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'company' => $company, | ||||
|             'income' => $invoicesAmount, | ||||
|             'expenseCategories' => $expenseCategories, | ||||
|             'totalExpense' => $totalAmount, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.profit-loss'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
| } | ||||
| @ -1,19 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Setting; | ||||
|  | ||||
| class SettingsController extends Controller | ||||
| { | ||||
|     public function getAppVersion(Request $request) | ||||
|     { | ||||
|         $version = Setting::getSetting('version'); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'version' => $version, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @ -1,35 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Space\Updater; | ||||
| use Crater\Space\SiteApi; | ||||
|  | ||||
| class UpdateController extends Controller | ||||
| { | ||||
|     public function update(Request $request) | ||||
|     { | ||||
|         set_time_limit(600); // 10 minutes | ||||
|  | ||||
|         $json = Updater::update($request->installed, $request->version); | ||||
|  | ||||
|         return response()->json($json); | ||||
|     } | ||||
|  | ||||
|     public function finishUpdate(Request $request) | ||||
|     { | ||||
|         $json = Updater::finishUpdate($request->installed, $request->version); | ||||
|  | ||||
|         return response()->json($json); | ||||
|     } | ||||
|  | ||||
|     public function checkLatestVersion(Request $request) | ||||
|     { | ||||
|         set_time_limit(600); // 10 minutes | ||||
|  | ||||
|         $json = Updater::checkForUpdate(); | ||||
|  | ||||
|         return response()->json($json); | ||||
|     } | ||||
| } | ||||
| @ -1,74 +0,0 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
|  | ||||
| use Illuminate\Http\Request; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\User; | ||||
| use Crater\Currency; | ||||
| use Crater\Setting; | ||||
| use Crater\Item; | ||||
| use Crater\TaxType; | ||||
| use DB; | ||||
| use Carbon\Carbon; | ||||
| use Auth; | ||||
| use Crater\Company; | ||||
| use Crater\CompanySetting; | ||||
|  | ||||
| class UsersController extends Controller | ||||
| { | ||||
|     public function getBootstrap(Request $request) | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
|  | ||||
|         $company = $request->header('company') ?? 1; | ||||
|  | ||||
|         $customers = User::with('billingAddress', 'shippingAddress') | ||||
|             ->customer() | ||||
|             ->whereCompany($company) | ||||
|             ->latest() | ||||
|             ->get(); | ||||
|  | ||||
|         $currencies = Currency::latest()->get(); | ||||
|  | ||||
|         $default_language = CompanySetting::getSetting('language', $company); | ||||
|  | ||||
|         $default_currency = Currency::findOrFail( | ||||
|             CompanySetting::getSetting('currency', $company) | ||||
|         ); | ||||
|  | ||||
|         $moment_date_format = CompanySetting::getSetting( | ||||
|             'moment_date_format', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         $fiscal_year = CompanySetting::getSetting( | ||||
|             'fiscal_year', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         $items = Item::all(); | ||||
|  | ||||
|         $taxTypes = TaxType::latest()->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'customers' => $customers, | ||||
|             'currencies' => $currencies, | ||||
|             'default_currency' => $default_currency, | ||||
|             'default_language' => $default_language, | ||||
|             'company' => $user->company, | ||||
|             'companies' => Company::all(), | ||||
|             'items' => $items, | ||||
|             'taxTypes' => $taxTypes, | ||||
|             'moment_date_format' => $moment_date_format, | ||||
|             'fiscal_year' => $fiscal_year, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function ping() | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'success' => 'crater-self-hosted' | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Http/Controllers/V1/Auth/ConfirmPasswordController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Http/Controllers/V1/Auth/ConfirmPasswordController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| use Illuminate\Foundation\Auth\ConfirmsPasswords; | ||||
|  | ||||
| class ConfirmPasswordController extends Controller | ||||
| { | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Confirm Password Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller is responsible for handling password confirmations and | ||||
|     | uses a simple trait to include the behavior. You're free to explore | ||||
|     | this trait and override any functions that require customization. | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     use ConfirmsPasswords; | ||||
|  | ||||
|     /** | ||||
|      * Where to redirect users when the intended url fails. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $redirectTo = RouteServiceProvider::HOME; | ||||
|  | ||||
|     /** | ||||
|      * Create a new controller instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->middleware('auth'); | ||||
|     } | ||||
| } | ||||
| @ -1,5 +1,6 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers\Auth; | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Foundation\Auth\SendsPasswordResetEmails; | ||||
| @ -20,16 +21,6 @@ class ForgotPasswordController extends Controller | ||||
| 
 | ||||
|     use SendsPasswordResetEmails; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new controller instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // $this->middleware('guest');
 | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the response for a successful password reset link. | ||||
|      * | ||||
							
								
								
									
										40
									
								
								app/Http/Controllers/V1/Auth/LoginController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Http/Controllers/V1/Auth/LoginController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| use Illuminate\Foundation\Auth\AuthenticatesUsers; | ||||
|  | ||||
| class LoginController extends Controller | ||||
| { | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Login Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller handles authenticating users for the application and | ||||
|     | redirecting them to your home screen. The controller uses a trait | ||||
|     | to conveniently provide its functionality to your applications. | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     use AuthenticatesUsers; | ||||
|  | ||||
|     /** | ||||
|      * Where to redirect users after login. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $redirectTo = RouteServiceProvider::HOME; | ||||
|  | ||||
|     /** | ||||
|      * Create a new controller instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->middleware('guest')->except('logout'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										72
									
								
								app/Http/Controllers/V1/Auth/RegisterController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								app/Http/Controllers/V1/Auth/RegisterController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,72 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| use Illuminate\Foundation\Auth\RegistersUsers; | ||||
| use Illuminate\Support\Facades\Validator; | ||||
|  | ||||
| class RegisterController extends Controller | ||||
| { | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Register Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller handles the registration of new users as well as their | ||||
|     | validation and creation. By default this controller uses a trait to | ||||
|     | provide this functionality without requiring any additional code. | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     use RegistersUsers; | ||||
|  | ||||
|     /** | ||||
|      * Where to redirect users after registration. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $redirectTo = RouteServiceProvider::HOME; | ||||
|  | ||||
|     /** | ||||
|      * Create a new controller instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->middleware('guest'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a validator for an incoming registration request. | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @return \Illuminate\Contracts\Validation\Validator | ||||
|      */ | ||||
|     protected function validator(array $data) | ||||
|     { | ||||
|         return Validator::make($data, [ | ||||
|             'name' => ['required', 'string', 'max:255'], | ||||
|             'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], | ||||
|             'password' => ['required', 'string', 'min:8', 'confirmed'], | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a new user instance after a valid registration. | ||||
|      * | ||||
|      * @param  array  $data | ||||
|      * @return \App\User | ||||
|      */ | ||||
|     protected function create(array $data) | ||||
|     { | ||||
|         return User::create([ | ||||
|             'name' => $data['name'], | ||||
|             'email' => $data['email'], | ||||
|             'password' => $data['password'], | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,11 +1,13 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers\Auth; | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| use Illuminate\Auth\Events\PasswordReset; | ||||
| use Illuminate\Foundation\Auth\ResetsPasswords; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Str; | ||||
| use Illuminate\Auth\Events\PasswordReset; | ||||
| 
 | ||||
| class ResetPasswordController extends Controller | ||||
| { | ||||
| @ -27,17 +29,7 @@ class ResetPasswordController extends Controller | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $redirectTo = '/'; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a new controller instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // $this->middleware('guest');
 | ||||
|     } | ||||
|     protected $redirectTo = RouteServiceProvider::HOME; | ||||
| 
 | ||||
|     /** | ||||
|      * Get the response for a successful password reset. | ||||
| @ -49,7 +41,7 @@ class ResetPasswordController extends Controller | ||||
|     protected function sendResetResponse(Request $request, $response) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'message' => 'Password reset successfully.' | ||||
|             'message' => 'Password reset successfully.', | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
| @ -62,7 +54,7 @@ class ResetPasswordController extends Controller | ||||
|      */ | ||||
|     protected function resetPassword($user, $password) | ||||
|     { | ||||
|         $user->password = \Hash::make($password); | ||||
|         $user->password = $password; | ||||
| 
 | ||||
|         $user->setRememberToken(Str::random(60)); | ||||
| 
 | ||||
							
								
								
									
										42
									
								
								app/Http/Controllers/V1/Auth/VerificationController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								app/Http/Controllers/V1/Auth/VerificationController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| use Illuminate\Foundation\Auth\VerifiesEmails; | ||||
|  | ||||
| class VerificationController extends Controller | ||||
| { | ||||
|     /* | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | Email Verification Controller | ||||
|     |-------------------------------------------------------------------------- | ||||
|     | | ||||
|     | This controller is responsible for handling email verification for any | ||||
|     | user that recently registered with the application. Emails may also | ||||
|     | be re-sent if the user didn't receive the original email message. | ||||
|     | | ||||
|     */ | ||||
|  | ||||
|     use VerifiesEmails; | ||||
|  | ||||
|     /** | ||||
|      * Where to redirect users after verification. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $redirectTo = RouteServiceProvider::HOME; | ||||
|  | ||||
|     /** | ||||
|      * Create a new controller instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->middleware('auth'); | ||||
|         $this->middleware('signed')->only('verify'); | ||||
|         $this->middleware('throttle:6,1')->only('verify', 'resend'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										22
									
								
								app/Http/Controllers/V1/Backup/ApiController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Http/Controllers/V1/Backup/ApiController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| <?php | ||||
|  | ||||
| // Implementation taken from nova-backup-tool - https://github.com/spatie/nova-backup-tool/ | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Backup; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\JsonResponse; | ||||
|  | ||||
| class ApiController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function respondSuccess(): JsonResponse | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										93
									
								
								app/Http/Controllers/V1/Backup/BackupsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								app/Http/Controllers/V1/Backup/BackupsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| <?php | ||||
|  | ||||
| // Implementation taken from nova-backup-tool - https://github.com/spatie/nova-backup-tool/ | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Backup; | ||||
|  | ||||
| use Crater\Jobs\CreateBackupJob; | ||||
| use Crater\Rules\Backup\PathToZip; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Cache; | ||||
| use Spatie\Backup\BackupDestination\Backup; | ||||
| use Spatie\Backup\BackupDestination\BackupDestination; | ||||
| use Spatie\Backup\Helpers\Format; | ||||
|  | ||||
| class BackupsController extends ApiController | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $configuredBackupDisks = config('backup.backup.destination.disks'); | ||||
|  | ||||
|         try { | ||||
|             $backupDestination = BackupDestination::create(config('filesystems.default'), config('backup.backup.name')); | ||||
|  | ||||
|             $backups = Cache::remember("backups-{$request->file_disk_id}", now()->addSeconds(4), function () use ($backupDestination) { | ||||
|                 return $backupDestination | ||||
|                     ->backups() | ||||
|                     ->map(function (Backup $backup) { | ||||
|                         return [ | ||||
|                             'path' => $backup->path(), | ||||
|                             'created_at' => $backup->date()->format('Y-m-d H:i:s'), | ||||
|                             'size' => Format::humanReadableSize($backup->size()), | ||||
|                         ]; | ||||
|                     }) | ||||
|                     ->toArray(); | ||||
|             }); | ||||
|  | ||||
|             return response()->json([ | ||||
|                 'backups' => $backups, | ||||
|                 'disks' => $configuredBackupDisks, | ||||
|             ]); | ||||
|         } catch (\Exception $e) { | ||||
|             return response()->json([ | ||||
|                 'backups' => [], | ||||
|                 'error' => 'invalid_disk_credentials', | ||||
|                 'error_message' => $e->getMessage(), | ||||
|                 'disks' => $configuredBackupDisks, | ||||
|             ]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(Request $request) | ||||
|     { | ||||
|         dispatch(new CreateBackupJob($request->all()))->onQueue(config('backup.queue.name')); | ||||
|  | ||||
|         return $this->respondSuccess(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function destroy($disk, Request $request) | ||||
|     { | ||||
|         $validated = $request->validate([ | ||||
|             'path' => ['required', new PathToZip()], | ||||
|         ]); | ||||
|  | ||||
|         $backupDestination = BackupDestination::create(config('filesystems.default'), config('backup.backup.name')); | ||||
|  | ||||
|         $backupDestination | ||||
|             ->backups() | ||||
|             ->first(function (Backup $backup) use ($validated) { | ||||
|                 return $backup->path() === $validated['path']; | ||||
|             }) | ||||
|             ->delete(); | ||||
|  | ||||
|         return $this->respondSuccess(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										57
									
								
								app/Http/Controllers/V1/Backup/DownloadBackupController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/Http/Controllers/V1/Backup/DownloadBackupController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| // Implementation taken from nova-backup-tool - https://github.com/spatie/nova-backup-tool/ | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Backup; | ||||
|  | ||||
| use Crater\Rules\Backup\PathToZip; | ||||
| use Illuminate\Http\Request; | ||||
| use Spatie\Backup\BackupDestination\Backup; | ||||
| use Spatie\Backup\BackupDestination\BackupDestination; | ||||
| use Symfony\Component\HttpFoundation\Response; | ||||
| use Symfony\Component\HttpFoundation\StreamedResponse; | ||||
|  | ||||
| class DownloadBackupController extends ApiController | ||||
| { | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $validated = $request->validate([ | ||||
|             'path' => ['required', new PathToZip()], | ||||
|         ]); | ||||
|  | ||||
|         $backupDestination = BackupDestination::create(config('filesystems.default'), config('backup.backup.name')); | ||||
|  | ||||
|         $backup = $backupDestination->backups()->first(function (Backup $backup) use ($validated) { | ||||
|             return $backup->path() === $validated['path']; | ||||
|         }); | ||||
|  | ||||
|         if (! $backup) { | ||||
|             return response('Backup not found', Response::HTTP_UNPROCESSABLE_ENTITY); | ||||
|         } | ||||
|  | ||||
|         return $this->respondWithBackupStream($backup); | ||||
|     } | ||||
|  | ||||
|     public function respondWithBackupStream(Backup $backup): StreamedResponse | ||||
|     { | ||||
|         $fileName = pathinfo($backup->path(), PATHINFO_BASENAME); | ||||
|  | ||||
|         $downloadHeaders = [ | ||||
|             'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', | ||||
|             'Content-Type' => 'application/zip', | ||||
|             'Content-Length' => $backup->size(), | ||||
|             'Content-Disposition' => 'attachment; filename="'.$fileName.'"', | ||||
|             'Pragma' => 'public', | ||||
|         ]; | ||||
|  | ||||
|         return response()->stream(function () use ($backup) { | ||||
|             $stream = $backup->stream(); | ||||
|  | ||||
|             fpassthru($stream); | ||||
|  | ||||
|             if (is_resource($stream)) { | ||||
|                 fclose($stream); | ||||
|             } | ||||
|         }, 200, $downloadHeaders); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										102
									
								
								app/Http/Controllers/V1/CustomField/CustomFieldsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								app/Http/Controllers/V1/CustomField/CustomFieldsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\CustomField; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\CustomFieldRequest; | ||||
| use Crater\Models\CustomField; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class CustomFieldsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
|  | ||||
|         $customFields = CustomField::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'type', | ||||
|                 'search', | ||||
|             ])) | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customFields' => $customFields, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\CustomFieldRequest  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(CustomFieldRequest $request) | ||||
|     { | ||||
|         $customField = CustomField::createCustomField($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customField' => $customField, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(CustomField $customField) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'customField' => $customField, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(CustomFieldRequest $request, CustomField $customField) | ||||
|     { | ||||
|         $customField->updateCustomField($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customField' => $customField, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  int  $id | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(CustomField $customField) | ||||
|     { | ||||
|         if ($customField->customFieldValue()->exists()) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'values_attached', | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $customField->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										146
									
								
								app/Http/Controllers/V1/Customer/CustomerStatsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								app/Http/Controllers/V1/Customer/CustomerStatsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,146 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Customer; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Expense; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class CustomerStatsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request, User $customer) | ||||
|     { | ||||
|         $i = 0; | ||||
|         $months = []; | ||||
|         $invoiceTotals = []; | ||||
|         $expenseTotals = []; | ||||
|         $receiptTotals = []; | ||||
|         $netProfits = []; | ||||
|         $monthCounter = 0; | ||||
|         $fiscalYear = CompanySetting::getSetting('fiscal_year', $request->header('company')); | ||||
|         $startDate = Carbon::now(); | ||||
|         $start = Carbon::now(); | ||||
|         $end = Carbon::now(); | ||||
|         $terms = explode('-', $fiscalYear); | ||||
|  | ||||
|         if ($terms[0] <= $start->month) { | ||||
|             $startDate->month($terms[0])->startOfMonth(); | ||||
|             $start->month($terms[0])->startOfMonth(); | ||||
|             $end->month($terms[0])->endOfMonth(); | ||||
|         } else { | ||||
|             $startDate->subYear()->month($terms[0])->startOfMonth(); | ||||
|             $start->subYear()->month($terms[0])->startOfMonth(); | ||||
|             $end->subYear()->month($terms[0])->endOfMonth(); | ||||
|         } | ||||
|  | ||||
|         if ($request->has('previous_year')) { | ||||
|             $startDate->subYear()->startOfMonth(); | ||||
|             $start->subYear()->startOfMonth(); | ||||
|             $end->subYear()->endOfMonth(); | ||||
|         } | ||||
|         while ($monthCounter < 12) { | ||||
|             array_push( | ||||
|                 $invoiceTotals, | ||||
|                 Invoice::whereBetween( | ||||
|                     'invoice_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                     ->whereCompany($request->header('company')) | ||||
|                     ->whereCustomer($customer->id) | ||||
|                     ->sum('total') ?? 0 | ||||
|             ); | ||||
|             array_push( | ||||
|                 $expenseTotals, | ||||
|                 Expense::whereBetween( | ||||
|                     'expense_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                     ->whereCompany($request->header('company')) | ||||
|                     ->whereUser($customer->id) | ||||
|                     ->sum('amount') ?? 0 | ||||
|             ); | ||||
|             array_push( | ||||
|                 $receiptTotals, | ||||
|                 Payment::whereBetween( | ||||
|                     'payment_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                     ->whereCompany($request->header('company')) | ||||
|                     ->whereCustomer($customer->id) | ||||
|                     ->sum('amount') ?? 0 | ||||
|             ); | ||||
|             array_push( | ||||
|                 $netProfits, | ||||
|                 ($receiptTotals[$i] - $expenseTotals[$i]) | ||||
|             ); | ||||
|             $i++; | ||||
|             array_push($months, $start->format('M')); | ||||
|             $monthCounter++; | ||||
|             $end->startOfMonth(); | ||||
|             $start->addMonth()->startOfMonth(); | ||||
|             $end->addMonth()->endOfMonth(); | ||||
|         } | ||||
|  | ||||
|         $start->subMonth()->endOfMonth(); | ||||
|  | ||||
|         $salesTotal = Invoice::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|                 'invoice_date', | ||||
|                 [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|             ) | ||||
|             ->whereCustomer($customer->id) | ||||
|             ->sum('total'); | ||||
|         $totalReceipts = Payment::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|                 'payment_date', | ||||
|                 [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|             ) | ||||
|             ->whereCustomer($customer->id) | ||||
|             ->sum('amount'); | ||||
|         $totalExpenses = Expense::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|                 'expense_date', | ||||
|                 [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|             ) | ||||
|             ->whereUser($customer->id) | ||||
|             ->sum('amount'); | ||||
|         $netProfit = (int) $totalReceipts - (int) $totalExpenses; | ||||
|  | ||||
|         $chartData = [ | ||||
|             'months' => $months, | ||||
|             'invoiceTotals' => $invoiceTotals, | ||||
|             'expenseTotals' => $expenseTotals, | ||||
|             'receiptTotals' => $receiptTotals, | ||||
|             'netProfit' => $netProfit, | ||||
|             'netProfits' => $netProfits, | ||||
|             'salesTotal' => $salesTotal, | ||||
|             'totalReceipts' => $totalReceipts, | ||||
|             'totalExpenses' => $totalExpenses, | ||||
|         ]; | ||||
|  | ||||
|         $customer = User::with([ | ||||
|             'billingAddress', | ||||
|             'shippingAddress', | ||||
|             'billingAddress.country', | ||||
|             'shippingAddress.country', | ||||
|             'currency', | ||||
|             'fields.customField', | ||||
|         ])->find($customer->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'chartData' => $chartData, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										120
									
								
								app/Http/Controllers/V1/Customer/CustomersController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								app/Http/Controllers/V1/Customer/CustomersController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,120 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Customer; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\DB; | ||||
|  | ||||
| class CustomersController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $customers = User::with('creator') | ||||
|             ->customer() | ||||
|             ->applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'contact_name', | ||||
|                 'display_name', | ||||
|                 'phone', | ||||
|                 'customer_id', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select( | ||||
|                 'users.*', | ||||
|                 DB::raw('sum(invoices.due_amount) as due_amount') | ||||
|             ) | ||||
|             ->groupBy('users.id') | ||||
|             ->leftJoin('invoices', 'users.id', '=', 'invoices.user_id') | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customers' => $customers, | ||||
|             'customerTotalCount' => User::whereRole('customer')->count(), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(Requests\CustomerRequest $request) | ||||
|     { | ||||
|         $customer = User::createCustomer($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  User $customer | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(User $customer) | ||||
|     { | ||||
|         $customer->load([ | ||||
|             'billingAddress.country', | ||||
|             'shippingAddress.country', | ||||
|             'fields.customField', | ||||
|             'creator', | ||||
|         ]); | ||||
|  | ||||
|         $currency = $customer->currency; | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'currency' => $currency, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Crater\Models\User $customer | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(Requests\CustomerRequest $request, User $customer) | ||||
|     { | ||||
|         $customer = User::updateCustomer($request, $customer); | ||||
|  | ||||
|         $customer = User::with('billingAddress', 'shippingAddress', 'fields')->find($customer->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove a list of Customers along side all their resources (ie. Estimates, Invoices, Payments and Addresses) | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         User::deleteCustomers($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Dashboard; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Expense; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class DashboardChartController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $expensesCategories = Expense::with('category') | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $amounts = $expensesCategories->pluck('total_amount'); | ||||
|         $names = $expensesCategories->pluck('category.name'); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'amounts' => $amounts, | ||||
|             'categories' => $names, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,21 +1,26 @@ | ||||
| <?php | ||||
| namespace Crater\Http\Controllers; | ||||
| 
 | ||||
| use Illuminate\Http\Request; | ||||
| namespace Crater\Http\Controllers\V1\Dashboard; | ||||
| 
 | ||||
| use Crater\Estimate; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Invoice; | ||||
| use Crater\CompanySetting; | ||||
| use Crater\Expense; | ||||
| use Crater\Payment; | ||||
| use Carbon\Carbon; | ||||
| use Crater\User; | ||||
| use Illuminate\Support\Facades\DB; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Expense; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| class DashboardController extends Controller | ||||
| { | ||||
|     public function index(Request $request) | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $invoiceTotals = []; | ||||
|         $expenseTotals = []; | ||||
| @ -23,14 +28,14 @@ class DashboardController extends Controller | ||||
|         $netProfits = []; | ||||
|         $i = 0; | ||||
|         $months = []; | ||||
|         $monthEnds = []; | ||||
|         $monthCounter = 0; | ||||
|         $fiscalYear = CompanySetting::getSetting('fiscal_year', $request->header('company')); | ||||
|         $startDate = Carbon::now(); | ||||
|         $start = Carbon::now(); | ||||
|         $end = Carbon::now(); | ||||
|         $terms = explode('-', $fiscalYear); | ||||
|         if ($terms[0] < $start->month) { | ||||
| 
 | ||||
|         if ($terms[0] <= $start->month) { | ||||
|             $startDate->month($terms[0])->startOfMonth(); | ||||
|             $start->month($terms[0])->startOfMonth(); | ||||
|             $end->month($terms[0])->endOfMonth(); | ||||
| @ -87,6 +92,7 @@ class DashboardController extends Controller | ||||
|         } | ||||
| 
 | ||||
|         $start->subMonth()->endOfMonth(); | ||||
| 
 | ||||
|         $salesTotal = Invoice::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|                 'invoice_date', | ||||
| @ -108,11 +114,11 @@ class DashboardController extends Controller | ||||
|         $netProfit = (int)$totalReceipts - (int)$totalExpenses; | ||||
| 
 | ||||
|         $chartData = [ | ||||
|             'months'        => $months, | ||||
|             'months' => $months, | ||||
|             'invoiceTotals' => $invoiceTotals, | ||||
|             'expenseTotals' => $expenseTotals, | ||||
|             'receiptTotals' => $receiptTotals, | ||||
|             'netProfits'    => $netProfits | ||||
|             'netProfits' => $netProfits, | ||||
|         ]; | ||||
| 
 | ||||
|         $customersCount = User::customer()->whereCompany($request->header('company'))->get()->count(); | ||||
| @ -133,23 +139,7 @@ class DashboardController extends Controller | ||||
|             'salesTotal' => $salesTotal, | ||||
|             'totalReceipts' => $totalReceipts, | ||||
|             'totalExpenses' => $totalExpenses, | ||||
|             'netProfit' => $netProfit | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     public function getExpenseChartData(Request $request) | ||||
|     { | ||||
|         $expensesCategories = Expense::with('category') | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
| 
 | ||||
|         $amounts = $expensesCategories->pluck('total_amount'); | ||||
|         $names = $expensesCategories->pluck('category.name'); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'amounts' => $amounts, | ||||
|             'categories' => $names, | ||||
|             'netProfit' => $netProfit, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Estimate; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class ChangeEstimateStatusController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @param  Estimate $estimate | ||||
|     * @return \Illuminate\Http\Response | ||||
|     */ | ||||
|     public function __invoke(Request $request, Estimate $estimate) | ||||
|     { | ||||
|         $estimate->update($request->only('status')); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,95 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
|  | ||||
| class ConvertEstimateController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @param  \Crater\Models\Estimate $estimate | ||||
|     * @return \Illuminate\Http\Response | ||||
|     */ | ||||
|     public function __invoke(Request $request, Estimate $estimate) | ||||
|     { | ||||
|         $estimate->load(['items', 'items.taxes', 'user', 'estimateTemplate', 'taxes']); | ||||
|  | ||||
|         $invoice_date = Carbon::now(); | ||||
|         $due_date = Carbon::now()->addDays(7); | ||||
|  | ||||
|         $invoice_prefix = CompanySetting::getSetting( | ||||
|             'invoice_prefix', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         $invoice = Invoice::create([ | ||||
|             'creator_id' => Auth::id(), | ||||
|             'invoice_date' => $invoice_date->format('Y-m-d'), | ||||
|             'due_date' => $due_date->format('Y-m-d'), | ||||
|             'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix), | ||||
|             'reference_number' => $estimate->reference_number, | ||||
|             'user_id' => $estimate->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_template_id' => 1, | ||||
|             'status' => Invoice::STATUS_DRAFT, | ||||
|             'paid_status' => Invoice::STATUS_UNPAID, | ||||
|             'sub_total' => $estimate->sub_total, | ||||
|             'discount' => $estimate->discount, | ||||
|             'discount_type' => $estimate->discount_type, | ||||
|             'discount_val' => $estimate->discount_val, | ||||
|             'total' => $estimate->total, | ||||
|             'due_amount' => $estimate->total, | ||||
|             'tax_per_item' => $estimate->tax_per_item, | ||||
|             'discount_per_item' => $estimate->discount_per_item, | ||||
|             'tax' => $estimate->tax, | ||||
|             'notes' => $estimate->notes, | ||||
|             'unique_hash' => str_random(60), | ||||
|         ]); | ||||
|  | ||||
|         $invoiceItems = $estimate->items->toArray(); | ||||
|  | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $invoiceItem['name'] = $invoiceItem['name']; | ||||
|             $item = $invoice->items()->create($invoiceItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) { | ||||
|                 foreach ($invoiceItem['taxes'] as $tax) { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|  | ||||
|                     if ($tax['amount']) { | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($estimate->taxes) { | ||||
|             foreach ($estimate->taxes->toArray() as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|                 unset($tax['estimate_id']); | ||||
|                 $invoice->taxes()->create($tax); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $invoice = Invoice::with([ | ||||
|             'items', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes', | ||||
|         ])->find($invoice->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoice' => $invoice, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								app/Http/Controllers/V1/Estimate/EstimatePdfController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Http/Controllers/V1/Estimate/EstimatePdfController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Estimate; | ||||
|  | ||||
| class EstimatePdfController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Estimate $estimate) | ||||
|     { | ||||
|         return $estimate->getGeneratedPDFOrStream('estimate'); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\EstimateTemplate; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class EstimateTemplatesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'templates' => EstimateTemplate::all(), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										104
									
								
								app/Http/Controllers/V1/Estimate/EstimatesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								app/Http/Controllers/V1/Estimate/EstimatesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,104 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeleteEstimatesRequest; | ||||
| use Crater\Http\Requests\EstimatesRequest; | ||||
| use Crater\Jobs\GenerateEstimatePdfJob; | ||||
| use Crater\Models\Estimate; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class EstimatesController extends Controller | ||||
| { | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $estimates = Estimate::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|                 'estimateTemplate', | ||||
|                 'taxes', | ||||
|                 'creator', | ||||
|             ]) | ||||
|             ->join('users', 'users.id', '=', 'estimates.user_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'status', | ||||
|                 'customer_id', | ||||
|                 'estimate_id', | ||||
|                 'estimate_number', | ||||
|                 'from_date', | ||||
|                 'to_date', | ||||
|                 'search', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('estimates.*', 'users.name') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         $siteData = [ | ||||
|             'estimates' => $estimates, | ||||
|             'estimateTotalCount' => Estimate::count(), | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($siteData); | ||||
|     } | ||||
|  | ||||
|     public function store(EstimatesRequest $request) | ||||
|     { | ||||
|         $estimate = Estimate::createEstimate($request); | ||||
|  | ||||
|         if ($request->has('estimateSend')) { | ||||
|             $estimate->send($request->title, $request->body); | ||||
|         } | ||||
|  | ||||
|         GenerateEstimatePdfJob::dispatch($estimate); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'estimate' => $estimate, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function show(Request $request, Estimate $estimate) | ||||
|     { | ||||
|         $estimate->load([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'estimateTemplate', | ||||
|             'creator', | ||||
|             'taxes', | ||||
|             'taxes.taxType', | ||||
|             'fields.customField', | ||||
|         ]); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'estimate' => $estimate, | ||||
|             'nextEstimateNumber' => $estimate->getEstimateNumAttribute(), | ||||
|             'estimatePrefix' => $estimate->getEstimatePrefixAttribute(), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function update(EstimatesRequest $request, Estimate $estimate) | ||||
|     { | ||||
|         $estimate = $estimate->updateEstimate($request); | ||||
|  | ||||
|         GenerateEstimatePdfJob::dispatch($estimate, true); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'estimate' => $estimate, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(DeleteEstimatesRequest $request) | ||||
|     { | ||||
|         Estimate::destroy($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								app/Http/Controllers/V1/Estimate/SendEstimateController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/Http/Controllers/V1/Estimate/SendEstimateController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendEstimatesRequest; | ||||
| use Crater\Models\Estimate; | ||||
|  | ||||
| class SendEstimateController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Crater\Http\Requests\SendEstimatesRequest  $request | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(SendEstimatesRequest $request, Estimate $estimate) | ||||
|     { | ||||
|         $response = $estimate->send($request->all()); | ||||
|  | ||||
|         return response()->json($response); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,35 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Expense; | ||||
|  | ||||
| class DownloadReceiptController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  Expense $expense | ||||
|      * @param   string $hash | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Expense $expense) | ||||
|     { | ||||
|         if ($expense) { | ||||
|             $media = $expense->getFirstMedia('receipts'); | ||||
|             if ($media) { | ||||
|                 $imagePath = $media->getPath(); | ||||
|                 $response = \Response::download($imagePath, $media->file_name); | ||||
|                 ob_end_clean(); | ||||
|  | ||||
|                 return $response; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'error' => 'receipt_not_found', | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										102
									
								
								app/Http/Controllers/V1/Expense/ExpenseCategoriesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								app/Http/Controllers/V1/Expense/ExpenseCategoriesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,102 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\ExpenseCategoryRequest; | ||||
| use Crater\Models\ExpenseCategory; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class ExpenseCategoriesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
|  | ||||
|         $categories = ExpenseCategory::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'category_id', | ||||
|                 'search', | ||||
|             ])) | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'categories' => $categories, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(ExpenseCategoryRequest $request) | ||||
|     { | ||||
|         $data = $request->validated(); | ||||
|         $data['company_id'] = $request->header('company'); | ||||
|         $category = ExpenseCategory::create($data); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\ExpenseCategory $category | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(ExpenseCategory $category) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Crater\Models\ExpenseCategory $ExpenseCategory | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(ExpenseCategoryRequest $request, ExpenseCategory $category) | ||||
|     { | ||||
|         $category->update($request->validated()); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\ExpensesCategory $category | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(ExpenseCategory $category) | ||||
|     { | ||||
|         if ($category->expenses() && $category->expenses()->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $category->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										101
									
								
								app/Http/Controllers/V1/Expense/ExpensesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								app/Http/Controllers/V1/Expense/ExpensesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,101 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeleteExpensesRequest; | ||||
| use Crater\Http\Requests\ExpenseRequest; | ||||
| use Crater\Models\Expense; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class ExpensesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $expenses = Expense::with('category', 'creator', 'fields') | ||||
|             ->leftJoin('users', 'users.id', '=', 'expenses.user_id') | ||||
|             ->join('expense_categories', 'expense_categories.id', '=', 'expenses.expense_category_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'expense_category_id', | ||||
|                 'user_id', | ||||
|                 'expense_id', | ||||
|                 'search', | ||||
|                 'from_date', | ||||
|                 'to_date', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('expenses.*', 'expense_categories.name', 'users.name as user_name') | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expenses' => $expenses, | ||||
|             'expenseTotalCount' => Expense::count(), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(ExpenseRequest $request) | ||||
|     { | ||||
|         $expense = Expense::createExpense($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\Expense $expense | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Expense $expense) | ||||
|     { | ||||
|         $expense->load('creator', 'fields.customField'); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Crater\Models\Expense $expense | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(ExpenseRequest $request, Expense $expense) | ||||
|     { | ||||
|         $expense->updateExpense($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(DeleteExpensesRequest $request) | ||||
|     { | ||||
|         Expense::destroy($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										40
									
								
								app/Http/Controllers/V1/Expense/ShowReceiptController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								app/Http/Controllers/V1/Expense/ShowReceiptController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Expense; | ||||
|  | ||||
| class ShowReceiptController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Retrieve details of an expense receipt from storage. | ||||
|      * | ||||
|      * @param   \Crater\Models\Expense $expense | ||||
|      * @return  \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Expense $expense) | ||||
|     { | ||||
|         $imagePath = null; | ||||
|  | ||||
|         if ($expense) { | ||||
|             $media = $expense->getFirstMedia('receipts'); | ||||
|             if ($media) { | ||||
|                 $imagePath = $media->getPath(); | ||||
|             } else { | ||||
|                 return response()->json([ | ||||
|                     'error' => 'receipt_does_not_exist', | ||||
|                 ]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $type = \File::mimeType($imagePath); | ||||
|  | ||||
|         $image = 'data:'.$type.';base64,'.base64_encode(file_get_contents($imagePath)); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'image' => $image, | ||||
|             'type' => $type, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										36
									
								
								app/Http/Controllers/V1/Expense/UploadReceiptController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								app/Http/Controllers/V1/Expense/UploadReceiptController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Expense; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class UploadReceiptController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Upload the expense receipts to storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  Expense $expense | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request, Expense $expense) | ||||
|     { | ||||
|         $data = json_decode($request->attachment_receipt); | ||||
|  | ||||
|         if ($data) { | ||||
|             if ($request->type === 'edit') { | ||||
|                 $expense->clearMediaCollection('receipts'); | ||||
|             } | ||||
|  | ||||
|             $expense->addMediaFromBase64($data->data) | ||||
|                 ->usingFileName($data->name) | ||||
|                 ->toMediaCollection('receipts', 'local'); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => 'Expense receipts uploaded successfully', | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										51
									
								
								app/Http/Controllers/V1/General/BootstrapController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/Http/Controllers/V1/General/BootstrapController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Auth; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Country; | ||||
| use Crater\Models\Currency; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class BootstrapController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
|  | ||||
|         $default_language = $user->getSettings(['language'])['language']; | ||||
|  | ||||
|         $settings = [ | ||||
|             'moment_date_format', | ||||
|             'carbon_date_format', | ||||
|             'fiscal_year', | ||||
|             'time_zone', | ||||
|             'currency', | ||||
|         ]; | ||||
|  | ||||
|         $settings = CompanySetting::getSettings($settings, $user->company_id); | ||||
|  | ||||
|         $default_currency = Currency::findOrFail($settings['currency']); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'company' => $user->company, | ||||
|             'currencies' => Currency::all(), | ||||
|             'countries' => Country::all(), | ||||
|             'default_currency' => $default_currency, | ||||
|             'default_language' => $default_language, | ||||
|             'moment_date_format' => $settings['moment_date_format'], | ||||
|             'carbon_date_format' => $settings['carbon_date_format'], | ||||
|             'fiscal_year' => $settings['fiscal_year'], | ||||
|             'time_zone' => $settings['time_zone'], | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								app/Http/Controllers/V1/General/CountriesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/Http/Controllers/V1/General/CountriesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Country; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class CountriesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'countries' => Country::all(), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								app/Http/Controllers/V1/General/CurrenciesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Http/Controllers/V1/General/CurrenciesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Currency; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class CurrenciesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $currencies = Currency::latest()->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'currencies' => $currencies, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								app/Http/Controllers/V1/General/DateFormatsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/Http/Controllers/V1/General/DateFormatsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\DateFormatter; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class DateFormatsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'date_formats' => DateFormatter::get_list(), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										22
									
								
								app/Http/Controllers/V1/General/FiscalYearsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Http/Controllers/V1/General/FiscalYearsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class FiscalYearsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'fiscal_years' => config('crater.fiscal_years'), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										22
									
								
								app/Http/Controllers/V1/General/LanguagesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								app/Http/Controllers/V1/General/LanguagesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class LanguagesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'languages' => config('crater.languages'), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								app/Http/Controllers/V1/General/NextNumberController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/Http/Controllers/V1/General/NextNumberController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class NextNumberController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $key = $request->key; | ||||
|  | ||||
|         $val = $key.'_prefix'; | ||||
|  | ||||
|         $prefix = CompanySetting::getSetting( | ||||
|             $val, | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         $nextNumber = null; | ||||
|  | ||||
|         switch ($key) { | ||||
|             case 'invoice': | ||||
|                 $nextNumber = Invoice::getNextInvoiceNumber($prefix); | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'estimate': | ||||
|                 $nextNumber = Estimate::getNextEstimateNumber($prefix); | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'payment': | ||||
|                 $nextNumber = Payment::getNextPaymentNumber($prefix); | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             default: | ||||
|                 return; | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'nextNumber' => $nextNumber, | ||||
|             'prefix' => $prefix, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										88
									
								
								app/Http/Controllers/V1/General/NotesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								app/Http/Controllers/V1/General/NotesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\NotesRequest; | ||||
| use Crater\Models\Note; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class NotesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->limit ?? 10; | ||||
|  | ||||
|         $notes = Note::latest() | ||||
|             ->applyFilters($request->only(['type', 'search'])) | ||||
|             ->paginate($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'notes' => $notes, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(NotesRequest $request) | ||||
|     { | ||||
|         $note = Note::create($request->validated()); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'note' => $note, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\Note  $note | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(Note $note) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'note' => $note, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Crater\Models\Note  $note | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(NotesRequest $request, Note $note) | ||||
|     { | ||||
|         $note->update($request->validated()); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'note' => $note, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\Models\Note  $note | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(Note $note) | ||||
|     { | ||||
|         $note->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										37
									
								
								app/Http/Controllers/V1/General/SearchController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								app/Http/Controllers/V1/General/SearchController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
|  | ||||
| class SearchController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $customers = User::where('role', 'customer') | ||||
|             ->applyFilters($request->only(['search'])) | ||||
|             ->latest() | ||||
|             ->paginate(10); | ||||
|  | ||||
|         if (Auth::user()->role == 'super admin') { | ||||
|             $users = User::where('role', 'admin') | ||||
|                 ->applyFilters($request->only(['search'])) | ||||
|                 ->latest() | ||||
|                 ->paginate(10); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'customers' => $customers, | ||||
|             'users' => $users ?? [], | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								app/Http/Controllers/V1/General/TimezonesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/Http/Controllers/V1/General/TimezonesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\TimeZones; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class TimezonesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'time_zones' => TimeZones::get_list(), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,34 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class ChangeInvoiceStatusController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(Request $request, Invoice $invoice) | ||||
|     { | ||||
|         if ($request->status == Invoice::STATUS_SENT) { | ||||
|             $invoice->status = Invoice::STATUS_SENT; | ||||
|             $invoice->sent = true; | ||||
|             $invoice->save(); | ||||
|         } elseif ($request->status == Invoice::STATUS_COMPLETED) { | ||||
|             $invoice->status = Invoice::STATUS_COMPLETED; | ||||
|             $invoice->paid_status = Invoice::STATUS_PAID; | ||||
|             $invoice->due_amount = 0; | ||||
|             $invoice->save(); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										91
									
								
								app/Http/Controllers/V1/Invoice/CloneInvoiceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								app/Http/Controllers/V1/Invoice/CloneInvoiceController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,91 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class CloneInvoiceController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Mail a specific invoice to the corresponding customer's email address. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request, Invoice $invoice) | ||||
|     { | ||||
|         $date = Carbon::now(); | ||||
|  | ||||
|         $invoice_prefix = CompanySetting::getSetting( | ||||
|             'invoice_prefix', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         $newInvoice = Invoice::create([ | ||||
|             'invoice_date' => $date->format('Y-m-d'), | ||||
|             'due_date' => $date->format('Y-m-d'), | ||||
|             'invoice_number' => $invoice_prefix."-".Invoice::getNextInvoiceNumber($invoice_prefix), | ||||
|             'reference_number' => $invoice->reference_number, | ||||
|             'user_id' => $invoice->user_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'invoice_template_id' => $invoice->invoice_template_id, | ||||
|             'status' => Invoice::STATUS_DRAFT, | ||||
|             'paid_status' => Invoice::STATUS_UNPAID, | ||||
|             'sub_total' => $invoice->sub_total, | ||||
|             'discount' => $invoice->discount, | ||||
|             'discount_type' => $invoice->discount_type, | ||||
|             'discount_val' => $invoice->discount_val, | ||||
|             'total' => $invoice->total, | ||||
|             'due_amount' => $invoice->total, | ||||
|             'tax_per_item' => $invoice->tax_per_item, | ||||
|             'discount_per_item' => $invoice->discount_per_item, | ||||
|             'tax' => $invoice->tax, | ||||
|             'notes' => $invoice->notes, | ||||
|             'unique_hash' => str_random(60), | ||||
|         ]); | ||||
|  | ||||
|         $invoice->load('items.taxes'); | ||||
|  | ||||
|         $invoiceItems = $invoice->items->toArray(); | ||||
|  | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $invoiceItem['name'] = $invoiceItem['name']; | ||||
|             $item = $newInvoice->items()->create($invoiceItem); | ||||
|  | ||||
|             if (array_key_exists('taxes', $invoiceItem) && $invoiceItem['taxes']) { | ||||
|                 foreach ($invoiceItem['taxes'] as $tax) { | ||||
|                     $tax['company_id'] = $request->header('company'); | ||||
|  | ||||
|                     if ($tax['amount']) { | ||||
|                         $item->taxes()->create($tax); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($invoice->taxes) { | ||||
|             foreach ($invoice->taxes->toArray() as $tax) { | ||||
|                 $tax['company_id'] = $request->header('company'); | ||||
|                 $newInvoice->taxes()->create($tax); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $newInvoice = Invoice::with([ | ||||
|                 'items', | ||||
|                 'user', | ||||
|                 'invoiceTemplate', | ||||
|                 'taxes', | ||||
|             ]) | ||||
|             ->find($newInvoice->id); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoice' => $newInvoice, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								app/Http/Controllers/V1/Invoice/InvoicePdfController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Http/Controllers/V1/Invoice/InvoicePdfController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Invoice; | ||||
|  | ||||
| class InvoicePdfController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Invoice $invoice) | ||||
|     { | ||||
|         return $invoice->getGeneratedPDFOrStream('invoice'); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\InvoiceTemplate; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class InvoiceTemplatesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $invoiceTemplates = InvoiceTemplate::all(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoiceTemplates' => $invoiceTemplates, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										128
									
								
								app/Http/Controllers/V1/Invoice/InvoicesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								app/Http/Controllers/V1/Invoice/InvoicesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,128 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Http\Requests\DeleteInvoiceRequest; | ||||
| use Crater\Jobs\GenerateInvoicePdfJob; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class InvoicesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $invoices = Invoice::with(['items', 'user', 'creator', 'invoiceTemplate', 'taxes']) | ||||
|             ->join('users', 'users.id', '=', 'invoices.user_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'status', | ||||
|                 'paid_status', | ||||
|                 'customer_id', | ||||
|                 'invoice_id', | ||||
|                 'invoice_number', | ||||
|                 'from_date', | ||||
|                 'to_date', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|                 'search', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('invoices.*', 'users.name') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoices' => $invoices, | ||||
|             'invoiceTotalCount' => Invoice::count(), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(Requests\InvoicesRequest $request) | ||||
|     { | ||||
|         $invoice = Invoice::createInvoice($request); | ||||
|  | ||||
|         if ($request->has('invoiceSend')) { | ||||
|             $invoice->send($request->subject, $request->body); | ||||
|         } | ||||
|  | ||||
|         GenerateInvoicePdfJob::dispatch($invoice); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoice' => $invoice, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\Invoice $invoice | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Invoice $invoice) | ||||
|     { | ||||
|         $invoice->load([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes.taxType', | ||||
|             'fields.customField', | ||||
|         ]); | ||||
|  | ||||
|         $siteData = [ | ||||
|             'invoice' => $invoice, | ||||
|             'nextInvoiceNumber' => $invoice->getInvoiceNumAttribute(), | ||||
|             'invoicePrefix' => $invoice->getInvoicePrefixAttribute(), | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($siteData); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  Invoice $invoice | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(Requests\InvoicesRequest $request, Invoice $invoice) | ||||
|     { | ||||
|         $invoice = $invoice->updateInvoice($request); | ||||
|  | ||||
|         GenerateInvoicePdfJob::dispatch($invoice, true); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'invoice' => $invoice, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * delete the specified resources in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function delete(DeleteInvoiceRequest $request) | ||||
|     { | ||||
|         Invoice::destroy($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								app/Http/Controllers/V1/Invoice/SendInvoiceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Http/Controllers/V1/Invoice/SendInvoiceController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendInvoiceRequest; | ||||
| use Crater\Models\Invoice; | ||||
|  | ||||
| class SendInvoiceController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Mail a specific invoice to the corresponding customer's email address. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(SendInvoiceRequest $request, Invoice $invoice) | ||||
|     { | ||||
|         $invoice->send($request->all()); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										106
									
								
								app/Http/Controllers/V1/Item/ItemsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								app/Http/Controllers/V1/Item/ItemsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,106 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Item; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Http\Requests\DeleteItemsRequest; | ||||
| use Crater\Models\Item; | ||||
| use Crater\Models\TaxType; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class ItemsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Retrieve a list of existing Items. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $items = Item::with(['taxes', 'creator']) | ||||
|             ->leftJoin('units', 'units.id', '=', 'items.unit_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'price', | ||||
|                 'unit_id', | ||||
|                 'item_id', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('items.*', 'units.name as unit_name') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'items' => $items, | ||||
|             'taxTypes' => TaxType::latest()->get(), | ||||
|             'itemTotalCount' => Item::count(), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create Item. | ||||
|      * | ||||
|      * @param  Crater\Http\Requests\ItemsRequest $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(Requests\ItemsRequest $request) | ||||
|     { | ||||
|         $item = Item::createItem($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * get an existing Item. | ||||
|      * | ||||
|      * @param  Item $item | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Item $item) | ||||
|     { | ||||
|         $item->load('taxes'); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update an existing Item. | ||||
|      * | ||||
|      * @param  Crater\Http\Requests\ItemsRequest $request | ||||
|      * @param  \Crater\Models\Item $item | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(Requests\ItemsRequest $request, Item $item) | ||||
|     { | ||||
|         $item = $item->updateItem($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete a list of existing Items. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function delete(DeleteItemsRequest $request) | ||||
|     { | ||||
|         Item::destroy($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										109
									
								
								app/Http/Controllers/V1/Item/UnitsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								app/Http/Controllers/V1/Item/UnitsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,109 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Item; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\UnitRequest; | ||||
| use Crater\Models\Unit; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class UnitsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
|  | ||||
|         $units = Unit::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'unit_id', | ||||
|             ])) | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'units' => $units, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(UnitRequest $request) | ||||
|     { | ||||
|         $data = $request->validated(); | ||||
|         $data['company_id'] = $request->header('company'); | ||||
|         $unit = Unit::create($data); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'unit' => $unit, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\Unit  $unit | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(Unit $unit) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'unit' => $unit, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Crater\Models\Unit  $unit | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(UnitRequest $request, Unit $unit) | ||||
|     { | ||||
|         $unit->update($request->validated()); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'unit' => $unit, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\Models\Unit  $unit | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(Unit $unit) | ||||
|     { | ||||
|         if ($unit->items()->exists()) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'items_attached', | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $unit->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => 'Unit deleted successfully', | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								app/Http/Controllers/V1/Mobile/AuthController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								app/Http/Controllers/V1/Mobile/AuthController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Mobile; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Hash; | ||||
| use Illuminate\Validation\ValidationException; | ||||
|  | ||||
| class AuthController extends Controller | ||||
| { | ||||
|     public function login(Request $request) | ||||
|     { | ||||
|         $request->validate([ | ||||
|             'username' => 'required|email', | ||||
|             'password' => 'required', | ||||
|             'device_name' => 'required', | ||||
|         ]); | ||||
|  | ||||
|         $user = User::where('email', $request->username)->first(); | ||||
|  | ||||
|         if (! $user || ! Hash::check($request->password, $user->password)) { | ||||
|             throw ValidationException::withMessages([ | ||||
|                 'email' => ['The provided credentials are incorrect.'], | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'type' => 'Bearer', | ||||
|             'token' => $user->createToken($request->device_name)->plainTextToken, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function logout(Request $request) | ||||
|     { | ||||
|         $request->user()->currentAccessToken()->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Mobile\Customer; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Mail\EstimateViewedMail; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\User; | ||||
|  | ||||
| class EstimatePdfController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Estimate $estimate) | ||||
|     { | ||||
|         if ($estimate && ($estimate->status == Estimate::STATUS_SENT || $estimate->status == Estimate::STATUS_DRAFT)) { | ||||
|             $estimate->status = Estimate::STATUS_VIEWED; | ||||
|             $estimate->save(); | ||||
|             $notifyEstimateViewed = CompanySetting::getSetting( | ||||
|                 'notify_estimate_viewed', | ||||
|                 $estimate->company_id | ||||
|             ); | ||||
|  | ||||
|             if ($notifyEstimateViewed == 'YES') { | ||||
|                 $data['estimate'] = Estimate::findOrFail($estimate->id)->toArray(); | ||||
|                 $data['user'] = User::find($estimate->user_id)->toArray(); | ||||
|                 $notificationEmail = CompanySetting::getSetting( | ||||
|                     'notification_email', | ||||
|                     $estimate->company_id | ||||
|                 ); | ||||
|  | ||||
|                 \Mail::to($notificationEmail)->send(new EstimateViewedMail($data)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $estimate->getGeneratedPDFOrStream('estimate'); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,44 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Mobile\Customer; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Mail\InvoiceViewedMail; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\User; | ||||
|  | ||||
| class InvoicePdfController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Invoice $invoice) | ||||
|     { | ||||
|         if ($invoice && ($invoice->status == Invoice::STATUS_SENT || $invoice->status == Invoice::STATUS_DRAFT)) { | ||||
|             $invoice->status = Invoice::STATUS_VIEWED; | ||||
|             $invoice->viewed = true; | ||||
|             $invoice->save(); | ||||
|             $notifyInvoiceViewed = CompanySetting::getSetting( | ||||
|                 'notify_invoice_viewed', | ||||
|                 $invoice->company_id | ||||
|             ); | ||||
|  | ||||
|             if ($notifyInvoiceViewed == 'YES') { | ||||
|                 $data['invoice'] = Invoice::findOrFail($invoice->id)->toArray(); | ||||
|                 $data['user'] = User::find($invoice->user_id)->toArray(); | ||||
|                 $notificationEmail = CompanySetting::getSetting( | ||||
|                     'notification_email', | ||||
|                     $invoice->company_id | ||||
|                 ); | ||||
|  | ||||
|                 \Mail::to($notificationEmail)->send(new InvoiceViewedMail($data)); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $invoice->getGeneratedPDFOrStream('invoice'); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,95 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DatabaseEnvironmentRequest; | ||||
| use Crater\Space\EnvironmentManager; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Artisan; | ||||
|  | ||||
| class DatabaseConfigurationController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * @var EnvironmentManager | ||||
|      */ | ||||
|     protected $EnvironmentManager; | ||||
|  | ||||
|     /** | ||||
|      * @param EnvironmentManager $environmentManager | ||||
|      */ | ||||
|     public function __construct(EnvironmentManager $environmentManager) | ||||
|     { | ||||
|         $this->environmentManager = $environmentManager; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param DatabaseEnvironmentRequest $request | ||||
|      */ | ||||
|     public function saveDatabaseEnvironment(DatabaseEnvironmentRequest $request) | ||||
|     { | ||||
|         Artisan::call('config:clear'); | ||||
|         Artisan::call('cache:clear'); | ||||
|  | ||||
|         $results = $this->environmentManager->saveDatabaseVariables($request); | ||||
|  | ||||
|         if (array_key_exists("success", $results)) { | ||||
|             Artisan::call('key:generate --force'); | ||||
|             Artisan::call('config:clear'); | ||||
|             Artisan::call('cache:clear'); | ||||
|             Artisan::call('storage:link'); | ||||
|             Artisan::call('migrate --seed --force'); | ||||
|         } | ||||
|  | ||||
|         return response()->json($results); | ||||
|     } | ||||
|  | ||||
|     public function getDatabaseEnvironment(Request $request) | ||||
|     { | ||||
|         $databaseData = []; | ||||
|  | ||||
|         switch ($request->connection) { | ||||
|             case 'sqlite': | ||||
|                 $databaseData = [ | ||||
|                     'database_connection' => 'sqlite', | ||||
|                     'database_name' => database_path('database.sqlite'), | ||||
|                 ]; | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'pgsql': | ||||
|                 $databaseData = [ | ||||
|                     'database_connection' => 'pgsql', | ||||
|                     'database_host' => '127.0.0.1', | ||||
|                     'database_port' => 5432, | ||||
|                 ]; | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'mysql': | ||||
|                 $databaseData = [ | ||||
|                     'database_connection' => 'mysql', | ||||
|                     'database_host' => '127.0.0.1', | ||||
|                     'database_port' => 3306, | ||||
|                 ]; | ||||
|  | ||||
|                 break; | ||||
|  | ||||
|             case 'sqlsrv': | ||||
|                 $databaseData = [ | ||||
|                     'driver' => 'sqlsrv', | ||||
|                     'host' => '127.0.0.1', | ||||
|                     'port' => 1433, | ||||
|                 ]; | ||||
|  | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return response()->json([ | ||||
|             'config' => $databaseData, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										25
									
								
								app/Http/Controllers/V1/Onboarding/FinishController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								app/Http/Controllers/V1/Onboarding/FinishController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
|  | ||||
| class FinishController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         \Storage::disk('local')->put('database_created', 'database_created'); | ||||
|  | ||||
|         $user = User::where('role', 'super admin')->first(); | ||||
|         Auth::login($user); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,46 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Setting; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class OnboardingWizardController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function getStep(Request $request) | ||||
|     { | ||||
|         if (! \Storage::disk('local')->has('database_created')) { | ||||
|             return response()->json([ | ||||
|                 'profile_complete' => 0, | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'profile_complete' => Setting::getSetting('profile_complete'), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function updateStep(Request $request) | ||||
|     { | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|  | ||||
|         if ($setting === 'COMPLETED') { | ||||
|             return response()->json([ | ||||
|                 'profile_complete' => $setting, | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         Setting::setSetting('profile_complete', $request->profile_complete); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'profile_complete' => Setting::getSetting('profile_complete'), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,7 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers; | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\PermissionsChecker; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| 
 | ||||
| @ -32,7 +33,7 @@ class PermissionsController extends Controller | ||||
|         ); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'permissions' => $permissions | ||||
|             'permissions' => $permissions, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,7 +1,8 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers; | ||||
| namespace Crater\Http\Controllers\V1\Onboarding; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\RequirementsChecker; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| 
 | ||||
| @ -36,7 +37,7 @@ class RequirementsController extends Controller | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'phpSupportInfo' => $phpSupportInfo, | ||||
|             'requirements' => $requirements | ||||
|             'requirements' => $requirements, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										100
									
								
								app/Http/Controllers/V1/Payment/PaymentMethodsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								app/Http/Controllers/V1/Payment/PaymentMethodsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,100 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\PaymentMethodRequest; | ||||
| use Crater\Models\PaymentMethod; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class PaymentMethodsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
|  | ||||
|         $paymentMethods = PaymentMethod::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'method_id', | ||||
|                 'search', | ||||
|             ])) | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'paymentMethods' => $paymentMethods, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(PaymentMethodRequest $request) | ||||
|     { | ||||
|         $paymentMethod = PaymentMethod::createPaymentMethod($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'paymentMethod' => $paymentMethod, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\PaymentMethod  $paymentMethod | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(PaymentMethod $paymentMethod) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'paymentMethod' => $paymentMethod, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Crater\Models\PaymentMethod  $paymentMethod | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(PaymentMethodRequest $request, PaymentMethod $paymentMethod) | ||||
|     { | ||||
|         $paymentMethod->update($request->validated()); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'paymentMethod' => $paymentMethod, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\Models\PaymentMethod  $paymentMethod | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(PaymentMethod $paymentMethod) | ||||
|     { | ||||
|         $payments = $paymentMethod->payments; | ||||
|  | ||||
|         if ($payments->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'payments_attached', | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $paymentMethod->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => 'Payment method deleted successfully', | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										20
									
								
								app/Http/Controllers/V1/Payment/PaymentPdfController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Http/Controllers/V1/Payment/PaymentPdfController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Payment; | ||||
|  | ||||
| class PaymentPdfController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Payment $payment) | ||||
|     { | ||||
|         return $payment->getGeneratedPDFOrStream('payment'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										96
									
								
								app/Http/Controllers/V1/Payment/PaymentsController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								app/Http/Controllers/V1/Payment/PaymentsController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,96 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeletePaymentsRequest; | ||||
| use Crater\Http\Requests\PaymentRequest; | ||||
| use Crater\Models\Payment; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class PaymentsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $payments = Payment::with(['user', 'invoice', 'paymentMethod', 'creator']) | ||||
|             ->join('users', 'users.id', '=', 'payments.user_id') | ||||
|             ->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id') | ||||
|             ->leftJoin('payment_methods', 'payment_methods.id', '=', 'payments.payment_method_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'payment_number', | ||||
|                 'payment_id', | ||||
|                 'payment_method_id', | ||||
|                 'customer_id', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->select('payments.*', 'users.name', 'invoices.invoice_number', 'payment_methods.name as payment_mode') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'payments' => $payments, | ||||
|             'paymentTotalCount' => Payment::count(), | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(PaymentRequest $request) | ||||
|     { | ||||
|         $payment = Payment::createPayment($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'payment' => $payment, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function show(Request $request, Payment $payment) | ||||
|     { | ||||
|         $payment->load([ | ||||
|             'user', | ||||
|             'invoice', | ||||
|             'paymentMethod', | ||||
|             'fields.customField', | ||||
|         ]); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'nextPaymentNumber' => $payment->getPaymentNumAttribute(), | ||||
|             'payment_prefix' => $payment->getPaymentPrefixAttribute(), | ||||
|             'payment' => $payment, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function update(PaymentRequest $request, Payment $payment) | ||||
|     { | ||||
|         $payment = $payment->updatePayment($request); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'payment' => $payment, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function delete(DeletePaymentsRequest $request) | ||||
|     { | ||||
|         Payment::deletePayments($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										23
									
								
								app/Http/Controllers/V1/Payment/SendPaymentController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/Http/Controllers/V1/Payment/SendPaymentController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendPaymentRequest; | ||||
| use Crater\Models\Payment; | ||||
|  | ||||
| class SendPaymentController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(SendPaymentRequest $request, Payment $payment) | ||||
|     { | ||||
|         $response = $payment->send($request->all()); | ||||
|  | ||||
|         return response()->json($response); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,92 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\App; | ||||
| use PDF; | ||||
|  | ||||
| class CustomerSalesReportController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @param  string  $hash | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(Request $request, $hash) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
|  | ||||
|         App::setLocale($locale); | ||||
|  | ||||
|         $start = Carbon::createFromFormat('Y-m-d', $request->from_date); | ||||
|         $end = Carbon::createFromFormat('Y-m-d', $request->to_date); | ||||
|  | ||||
|         $customers = User::with(['invoices' => function ($query) use ($start, $end) { | ||||
|             $query->whereBetween( | ||||
|                 'invoice_date', | ||||
|                 [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|             ); | ||||
|         }]) | ||||
|             ->customer() | ||||
|             ->whereCompany($company->id) | ||||
|             ->applyInvoiceFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($customers as $customer) { | ||||
|             $customerTotalAmount = 0; | ||||
|             foreach ($customer->invoices as $invoice) { | ||||
|                 $customerTotalAmount += $invoice->total; | ||||
|             } | ||||
|             $customer->totalAmount = $customerTotalAmount; | ||||
|             $totalAmount += $customerTotalAmount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color', | ||||
|         ]; | ||||
|  | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'customers' => $customers, | ||||
|             'totalAmount' => $totalAmount, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date, | ||||
|         ]); | ||||
|  | ||||
|         $pdf = PDF::loadView('app.pdf.reports.sales-customers'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								app/Http/Controllers/V1/Report/ExpensesReportController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								app/Http/Controllers/V1/Report/ExpensesReportController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Expense; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\App; | ||||
| use PDF; | ||||
|  | ||||
| class ExpensesReportController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @param  string  $hash | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(Request $request, $hash) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
|  | ||||
|         App::setLocale($locale); | ||||
|  | ||||
|         $expenseCategories = Expense::with('category') | ||||
|         ->whereCompany($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($expenseCategories as $category) { | ||||
|             $totalAmount += $category->total_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color', | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'expenseCategories' => $expenseCategories, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'totalExpense' => $totalAmount, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date, | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.expenses'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										76
									
								
								app/Http/Controllers/V1/Report/ItemSalesReportController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								app/Http/Controllers/V1/Report/ItemSalesReportController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,76 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\InvoiceItem; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\App; | ||||
| use PDF; | ||||
|  | ||||
| class ItemSalesReportController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @param  string  $hash | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(Request $request, $hash) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
|  | ||||
|         App::setLocale($locale); | ||||
|  | ||||
|         $items = InvoiceItem::whereCompany($company->id) | ||||
|             ->applyInvoiceFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->itemAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($items as $item) { | ||||
|             $totalAmount += $item->total_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color', | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'items' => $items, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'totalAmount' => $totalAmount, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date, | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.sales-items'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,85 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Expense; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\App; | ||||
| use PDF; | ||||
|  | ||||
| class ProfitLossReportController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Illuminate\Http\Request  $request | ||||
|     * @param  string  $hash | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(Request $request, $hash) | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
|  | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
|  | ||||
|         App::setLocale($locale); | ||||
|  | ||||
|         $invoicesAmount = Invoice::whereCompany($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->wherePaidStatus(Invoice::STATUS_PAID) | ||||
|             ->sum('total'); | ||||
|  | ||||
|         $expenseCategories = Expense::with('category') | ||||
|         ->whereCompany($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
|  | ||||
|         $totalAmount = 0; | ||||
|         foreach ($expenseCategories as $category) { | ||||
|             $totalAmount += $category->total_amount; | ||||
|         } | ||||
|  | ||||
|         $dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id); | ||||
|         $from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat); | ||||
|         $to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat); | ||||
|  | ||||
|         $colors = [ | ||||
|             'primary_text_color', | ||||
|             'heading_text_color', | ||||
|             'section_heading_text_color', | ||||
|             'border_color', | ||||
|             'body_text_color', | ||||
|             'footer_text_color', | ||||
|             'footer_total_color', | ||||
|             'footer_bg_color', | ||||
|             'date_text_color', | ||||
|         ]; | ||||
|         $colorSettings = CompanySetting::whereIn('option', $colors) | ||||
|             ->whereCompany($company->id) | ||||
|             ->get(); | ||||
|  | ||||
|         view()->share([ | ||||
|             'company' => $company, | ||||
|             'income' => $invoicesAmount, | ||||
|             'expenseCategories' => $expenseCategories, | ||||
|             'totalExpense' => $totalAmount, | ||||
|             'colorSettings' => $colorSettings, | ||||
|             'company' => $company, | ||||
|             'from_date' => $from_date, | ||||
|             'to_date' => $to_date, | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.profit-loss'); | ||||
|  | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
|  | ||||
|         return $pdf->stream(); | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	