mirror of
				https://github.com/crater-invoice/crater.git
				synced 2025-10-28 12:11:08 -04:00 
			
		
		
		
	Compare commits
	
		
			71 Commits
		
	
	
		
			csfixer-te
			...
			5.0.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 082d5cacf2 | |||
| d332712c22 | |||
| f434c3e0d1 | |||
| c810ad5246 | |||
| 29705662e3 | |||
| 31bfaadfad | |||
| e2299794ad | |||
| 7d71cc1607 | |||
| 40d9ecfe02 | |||
| 3d3d7d0ec0 | |||
| 63b1ee5849 | |||
| bfe13ef79d | |||
| 010c7b02ed | |||
| 81739d4db7 | |||
| 05110526a7 | |||
| 15bff7cd3f | |||
| 37470fe7a2 | |||
| 1a50aca26d | |||
| 8219d19222 | |||
| 8fa0252779 | |||
| 6bfab30f14 | |||
| d972279adc | |||
| 900a18c479 | |||
| 433c6a7c44 | |||
| 9f673d7eb3 | |||
| d3a745605e | |||
| b004e7e379 | |||
| 9893108539 | |||
| 2b80082996 | |||
| 8d596f5c19 | |||
| ce4335d8fa | |||
| 5eaea3ad59 | |||
| 375d4d428e | |||
| 2ec87baa6f | |||
| 18a2e83348 | |||
| d53e227b08 | |||
| 7721bf6f93 | |||
| 76977c3d2a | |||
| 512983deee | |||
| f5c23b33da | |||
| a0898a1fa0 | |||
| 236db087ba | |||
| 4772079d13 | |||
| 0e0ef1d99e | |||
| 3d9a73f9ec | |||
| b452c3f173 | |||
| 87667be90c | |||
| 31481739f1 | |||
| da43797d9c | |||
| e1fcf0695c | |||
| a52d5bc582 | |||
| e7bf86f9c0 | |||
| fca7d164a6 | |||
| 4b603f8823 | |||
| 4552138787 | |||
| d1dd704cdf | |||
| 00961bcae1 | |||
| 98ba17e56a | |||
| 8eb47b553e | |||
| 2fb46a4ab3 | |||
| 6fcddd6feb | |||
| 43c871f374 | |||
| 4ec9b2e817 | |||
| f2c6e06c54 | |||
| f95b292717 | |||
| 6ecd9728d4 | |||
| b2d4b7212b | |||
| b4956d38f7 | |||
| ed966b02eb | |||
| bcbffdcf30 | |||
| 3cf70135f3 | 
| @ -20,3 +20,6 @@ indent_size = 2 | ||||
|  | ||||
| [*.js] | ||||
| indent_size = 2 | ||||
|  | ||||
| [*.json] | ||||
| indent_size = 2 | ||||
|  | ||||
| @ -9,5 +9,5 @@ MAIL_PORT=587 | ||||
| MAIL_USERNAME=ff538f0e1037f4 | ||||
| MAIL_PASSWORD=c04c81145fcb73 | ||||
| MAIL_ENCRYPTION=tls | ||||
| MAIL_FROM_ADDRESS="admin@crater.com" | ||||
| MAIL_FROM_ADDRESS="admin@craterapp.com" | ||||
| MAIL_FROM_NAME="John Doe" | ||||
|  | ||||
							
								
								
									
										24
									
								
								.eslintrc.js
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								.eslintrc.js
									
									
									
									
									
								
							| @ -1,20 +1,14 @@ | ||||
| // .eslintrc.js | ||||
|  | ||||
| module.exports = { | ||||
|   root: true, | ||||
|   env: { | ||||
|     node: true, | ||||
|   }, | ||||
|   extends: [ | ||||
|     'plugin:vue/recommended', | ||||
|     'eslint:recommended', | ||||
|     'prettier/vue', | ||||
|     'plugin:prettier/recommended', | ||||
|     // add more generic rulesets here, such as: | ||||
|     // 'eslint:recommended', | ||||
|     "plugin:vue/vue3-recommended", | ||||
|     "prettier", | ||||
|   ], | ||||
|   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', | ||||
|     // override/add rules settings here, such as: | ||||
|     // 'vue/no-unused-vars': 'error' | ||||
|   }, | ||||
| } | ||||
| }; | ||||
|  | ||||
							
								
								
									
										77
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -1,39 +1,44 @@ | ||||
| FROM php:7.4-fpm | ||||
| FROM php:7.4-fpm-alpine | ||||
|  | ||||
| # Arguments defined in docker-compose.yml | ||||
| ARG user | ||||
| ARG uid | ||||
|  | ||||
| # 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 | ||||
|  | ||||
| # Clear cache | ||||
| RUN apt-get clean && rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
| RUN pecl install imagick \  | ||||
|     && docker-php-ext-enable imagick | ||||
|  | ||||
| # Install PHP extensions | ||||
| RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl bcmath gd  | ||||
|  | ||||
| # Get latest Composer | ||||
| COPY --from=composer:latest /usr/bin/composer /usr/bin/composer | ||||
|  | ||||
| # 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 | ||||
|  | ||||
| # Set working directory | ||||
| WORKDIR /var/www | ||||
|  | ||||
| USER $user | ||||
| RUN apk add --no-cache \ | ||||
|             $PHPIZE_DEPS \ | ||||
|             freetype-dev \ | ||||
|             git \ | ||||
|             zip \ | ||||
|             libzip-dev \ | ||||
|             php7-bcmath \ | ||||
|             curl \ | ||||
|             unzip \ | ||||
|             libjpeg-turbo-dev \ | ||||
|             libpng-dev \ | ||||
|             libxml2-dev \ | ||||
|             mariadb-client \ | ||||
|             sqlite \ | ||||
|             php7-json \ | ||||
|             php7-openssl \ | ||||
|             php7-pdo \ | ||||
|             php7-pdo_mysql \ | ||||
|             php7-session \ | ||||
|             php7-simplexml \ | ||||
|             php7-tokenizer \ | ||||
|             php7-xml \ | ||||
|             imagemagick \ | ||||
|             imagemagick-libs \ | ||||
|             imagemagick-dev \ | ||||
|             php7-imagick \ | ||||
|             php7-pcntl \ | ||||
|             --repository http://dl-cdn.alpinelinux.org/alpine/v3.13/community/ gnu-libiconv=1.15-r3 | ||||
|  | ||||
| ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so php | ||||
|  | ||||
| RUN printf "\n" | pecl install \ | ||||
| 		imagick && \ | ||||
| 		docker-php-ext-enable --ini-name 20-imagick.ini imagick | ||||
|  | ||||
| RUN docker-php-ext-configure zip | ||||
| RUN docker-php-ext-install zip | ||||
| RUN docker-php-ext-install iconv pdo pdo_mysql bcmath pcntl exif | ||||
| RUN docker-php-ext-configure gd --with-jpeg --with-freetype | ||||
| RUN docker-php-ext-install gd | ||||
|  | ||||
							
								
								
									
										63
									
								
								app/Console/Commands/CreateTemplateCommand.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								app/Console/Commands/CreateTemplateCommand.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,63 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Console\Commands; | ||||
|  | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\Facades\Storage; | ||||
|  | ||||
| class CreateTemplateCommand extends Command | ||||
| { | ||||
|     /** | ||||
|      * The name and signature of the console command. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $signature = 'make:template {name} {--type=}'; | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Create estimate or invoice pdf template.                               '; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function handle() | ||||
|     { | ||||
|         $templateName = $this->argument('name'); | ||||
|         $type = $this->option('type'); | ||||
|  | ||||
|         if (! $type) { | ||||
|             $type = $this->choice('Create a template for?', ['invoice', 'estimate']); | ||||
|         } | ||||
|  | ||||
|         if (Storage::disk('views')->exists("/app/pdf/{$type}/{$templateName}.blade.php")) { | ||||
|             $this->info("Template with given name already exists."); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         Storage::disk('views')->copy("/app/pdf/{$type}/{$type}1.blade.php", "/app/pdf/{$type}/{$templateName}.blade.php"); | ||||
|         copy(resource_path("/static/img/PDF/{$type}1.png"), resource_path("/static/img/PDF/{$templateName}.png")); | ||||
|  | ||||
|         $path = resource_path("app/pdf/{$type}/{$templateName}.blade.php"); | ||||
|         $type = ucfirst($type); | ||||
|         $this->info("{$type} Template created successfully at ".$path); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| @ -2,6 +2,7 @@ | ||||
|  | ||||
| namespace Crater\Console; | ||||
|  | ||||
| use Crater\Models\RecurringInvoice; | ||||
| use Illuminate\Console\Scheduling\Schedule; | ||||
| use Illuminate\Foundation\Console\Kernel as ConsoleKernel; | ||||
|  | ||||
| @ -15,6 +16,7 @@ class Kernel extends ConsoleKernel | ||||
|     protected $commands = [ | ||||
|         Commands\ResetApp::class, | ||||
|         Commands\UpdateCommand::class, | ||||
|         Commands\CreateTemplateCommand::class | ||||
|     ]; | ||||
|  | ||||
|     /** | ||||
| @ -30,6 +32,13 @@ class Kernel extends ConsoleKernel | ||||
|  | ||||
|         $schedule->command('check:estimates:status') | ||||
|             ->daily(); | ||||
|  | ||||
|         $recurringInvoices = RecurringInvoice::where('status', 'ACTIVE')->get(); | ||||
|         foreach ($recurringInvoices as $recurringInvoice) { | ||||
|             $schedule->call(function () use ($recurringInvoice) { | ||||
|                 $recurringInvoice->generateInvoice(); | ||||
|             })->cron($recurringInvoice->frequency); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Foundation\Auth\SendsPasswordResetEmails; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Auth; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Auth; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Providers\RouteServiceProvider; | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
| // Implementation taken from nova-backup-tool - https://github.com/spatie/nova-backup-tool/
 | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Backup; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Backup; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
| // Implementation taken from nova-backup-tool - https://github.com/spatie/nova-backup-tool/
 | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Backup; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Backup; | ||||
| 
 | ||||
| use Crater\Jobs\CreateBackupJob; | ||||
| use Crater\Rules\Backup\PathToZip; | ||||
| @ -22,6 +22,8 @@ class BackupsController extends ApiController | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage backups'); | ||||
| 
 | ||||
|         $configuredBackupDisks = config('backup.backup.destination.disks'); | ||||
| 
 | ||||
|         try { | ||||
| @ -62,6 +64,8 @@ class BackupsController extends ApiController | ||||
|      */ | ||||
|     public function store(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage backups'); | ||||
| 
 | ||||
|         dispatch(new CreateBackupJob($request->all()))->onQueue(config('backup.queue.name')); | ||||
| 
 | ||||
|         return $this->respondSuccess(); | ||||
| @ -75,6 +79,8 @@ class BackupsController extends ApiController | ||||
|      */ | ||||
|     public function destroy($disk, Request $request) | ||||
|     { | ||||
|         $this->authorize('manage backups'); | ||||
| 
 | ||||
|         $validated = $request->validate([ | ||||
|             'path' => ['required', new PathToZip()], | ||||
|         ]); | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
| // Implementation taken from nova-backup-tool - https://github.com/spatie/nova-backup-tool/
 | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Backup; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Backup; | ||||
| 
 | ||||
| use Crater\Rules\Backup\PathToZip; | ||||
| use Illuminate\Http\Request; | ||||
| @ -15,6 +15,8 @@ class DownloadBackupController extends ApiController | ||||
| { | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage backups'); | ||||
| 
 | ||||
|         $validated = $request->validate([ | ||||
|             'path' => ['required', new PathToZip()], | ||||
|         ]); | ||||
| @ -0,0 +1,85 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Company; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\CompaniesRequest; | ||||
| use Crater\Http\Resources\CompanyResource; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Silber\Bouncer\BouncerFacade; | ||||
| use Vinkla\Hashids\Facades\Hashids; | ||||
|  | ||||
| class CompaniesController extends Controller | ||||
| { | ||||
|     public function store(CompaniesRequest $request) | ||||
|     { | ||||
|         $this->authorize('create company'); | ||||
|  | ||||
|         $user = $request->user(); | ||||
|  | ||||
|         $company = Company::create($request->getCompanyPayload()); | ||||
|         $company->unique_hash = Hashids::connection(Company::class)->encode($company->id); | ||||
|         $company->save(); | ||||
|         $company->setupDefaultData(); | ||||
|         $user->companies()->attach($company->id); | ||||
|         $user->assign('super admin'); | ||||
|  | ||||
|         if ($request->address) { | ||||
|             $company->address()->create($request->address); | ||||
|         } | ||||
|  | ||||
|         return new CompanyResource($company); | ||||
|     } | ||||
|  | ||||
|     public function destroy(Request $request) | ||||
|     { | ||||
|         $company = Company::find($request->header('company')); | ||||
|  | ||||
|         $this->authorize('delete company', $company); | ||||
|  | ||||
|         $user = $request->user(); | ||||
|  | ||||
|         if ($request->name !== $company->name) { | ||||
|             return respondJson('company_name_must_match_with_given_name', 'Company name must match with given name'); | ||||
|         } | ||||
|  | ||||
|         if ($user->loadCount('companies')->companies_count <= 1) { | ||||
|             return respondJson('You_cannot_delete_all_companies', 'You cannot delete all companies'); | ||||
|         } | ||||
|  | ||||
|         $company->deleteCompany($user); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function transferOwnership(Request $request, User $user) | ||||
|     { | ||||
|         $company = Company::find($request->header('company')); | ||||
|         $this->authorize('transfer company ownership', $company); | ||||
|  | ||||
|         if ($user->hasCompany($company->id)) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'User does not belongs to this company.' | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         $company->update(['owner_id' => $user->id]); | ||||
|         BouncerFacade::sync($user)->roles(['super admin']); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function getUserCompanies(Request $request) | ||||
|     { | ||||
|         $companies = $request->user()->companies; | ||||
|  | ||||
|         return CompanyResource::collection($companies); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										24
									
								
								app/Http/Controllers/V1/Admin/Company/CompanyController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								app/Http/Controllers/V1/Admin/Company/CompanyController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Company; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\CompanyResource; | ||||
| use Crater\Models\Company; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class CompanyController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $company = Company::find($request->header('company')); | ||||
|  | ||||
|         return new CompanyResource($company); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Config; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Config; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
| @ -1,12 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Config; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| class MigrateUpdateController extends Controller | ||||
| class RetrospectiveEditsController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
| @ -16,10 +15,8 @@ class MigrateUpdateController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         Updater::migrateUpdate(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|             'retrospective_edits' => config('crater.retrospective_edits'), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\CustomField; | ||||
| namespace Crater\Http\Controllers\V1\Admin\CustomField; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\CustomFieldRequest; | ||||
| use Crater\Http\Resources\CustomFieldResource; | ||||
| use Crater\Models\CustomField; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,20 +17,16 @@ class CustomFieldsController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', CustomField::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
| 
 | ||||
|         $customFields = CustomField::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'type', | ||||
|                 'search', | ||||
|             ])) | ||||
|         $customFields = CustomField::applyFilters($request->all()) | ||||
|             ->whereCompany() | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'customFields' => $customFields, | ||||
|         ]); | ||||
|         return CustomFieldResource::collection($customFields); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -40,12 +37,11 @@ class CustomFieldsController extends Controller | ||||
|      */ | ||||
|     public function store(CustomFieldRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', CustomField::class); | ||||
| 
 | ||||
|         $customField = CustomField::createCustomField($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'customField' => $customField, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new CustomFieldResource($customField); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -56,10 +52,9 @@ class CustomFieldsController extends Controller | ||||
|      */ | ||||
|     public function show(CustomField $customField) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'customField' => $customField, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         $this->authorize('view', $customField); | ||||
| 
 | ||||
|         return new CustomFieldResource($customField); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -71,12 +66,11 @@ class CustomFieldsController extends Controller | ||||
|      */ | ||||
|     public function update(CustomFieldRequest $request, CustomField $customField) | ||||
|     { | ||||
|         $this->authorize('update', $customField); | ||||
| 
 | ||||
|         $customField->updateCustomField($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'customField' => $customField, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new CustomFieldResource($customField); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -87,13 +81,13 @@ class CustomFieldsController extends Controller | ||||
|      */ | ||||
|     public function destroy(CustomField $customField) | ||||
|     { | ||||
|         if ($customField->customFieldValue()->exists()) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'values_attached', | ||||
|             ]); | ||||
|         $this->authorize('delete', $customField); | ||||
| 
 | ||||
|         if ($customField->customFieldValues()->exists()) { | ||||
|             $customField->customFieldValues()->delete(); | ||||
|         } | ||||
| 
 | ||||
|         $customField->delete(); | ||||
|         $customField->forceDelete(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
| @ -1,14 +1,15 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Customer; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Customer; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\CustomerResource; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Customer; | ||||
| use Crater\Models\Expense; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| class CustomerStatsController extends Controller | ||||
| @ -19,8 +20,10 @@ class CustomerStatsController extends Controller | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request, User $customer) | ||||
|     public function __invoke(Request $request, Customer $customer) | ||||
|     { | ||||
|         $this->authorize('view', $customer); | ||||
| 
 | ||||
|         $i = 0; | ||||
|         $months = []; | ||||
|         $invoiceTotals = []; | ||||
| @ -56,7 +59,7 @@ class CustomerStatsController extends Controller | ||||
|                     'invoice_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                     ->whereCompany($request->header('company')) | ||||
|                     ->whereCompany() | ||||
|                     ->whereCustomer($customer->id) | ||||
|                     ->sum('total') ?? 0 | ||||
|             ); | ||||
| @ -66,7 +69,7 @@ class CustomerStatsController extends Controller | ||||
|                     'expense_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                     ->whereCompany($request->header('company')) | ||||
|                     ->whereCompany() | ||||
|                     ->whereUser($customer->id) | ||||
|                     ->sum('amount') ?? 0 | ||||
|             ); | ||||
| @ -76,7 +79,7 @@ class CustomerStatsController extends Controller | ||||
|                     'payment_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                     ->whereCompany($request->header('company')) | ||||
|                     ->whereCompany() | ||||
|                     ->whereCustomer($customer->id) | ||||
|                     ->sum('amount') ?? 0 | ||||
|             ); | ||||
| @ -94,25 +97,25 @@ class CustomerStatsController extends Controller | ||||
| 
 | ||||
|         $start->subMonth()->endOfMonth(); | ||||
| 
 | ||||
|         $salesTotal = Invoice::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|         $salesTotal = Invoice::whereBetween( | ||||
|             'invoice_date', | ||||
|             [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|         ) | ||||
|             ->whereCompany() | ||||
|             ->whereCustomer($customer->id) | ||||
|             ->sum('total'); | ||||
|         $totalReceipts = Payment::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|         $totalReceipts = Payment::whereBetween( | ||||
|             'payment_date', | ||||
|             [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|         ) | ||||
|             ->whereCompany() | ||||
|             ->whereCustomer($customer->id) | ||||
|             ->sum('amount'); | ||||
|         $totalExpenses = Expense::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|         $totalExpenses = Expense::whereBetween( | ||||
|             'expense_date', | ||||
|             [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|         ) | ||||
|             ->whereCompany() | ||||
|             ->whereUser($customer->id) | ||||
|             ->sum('amount'); | ||||
|         $netProfit = (int) $totalReceipts - (int) $totalExpenses; | ||||
| @ -129,18 +132,11 @@ class CustomerStatsController extends Controller | ||||
|             'totalExpenses' => $totalExpenses, | ||||
|         ]; | ||||
| 
 | ||||
|         $customer = User::with([ | ||||
|             'billingAddress', | ||||
|             'shippingAddress', | ||||
|             'billingAddress.country', | ||||
|             'shippingAddress.country', | ||||
|             'currency', | ||||
|             'fields.customField', | ||||
|         ])->find($customer->id); | ||||
|         $customer = Customer::find($customer->id); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'customer' => $customer, | ||||
|             'chartData' => $chartData, | ||||
|         ]); | ||||
|         return (new CustomerResource($customer)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'chartData' => $chartData | ||||
|             ]]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										108
									
								
								app/Http/Controllers/V1/Admin/Customer/CustomersController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								app/Http/Controllers/V1/Admin/Customer/CustomersController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,108 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Customer; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Http\Requests\DeleteCustomersRequest; | ||||
| use Crater\Http\Resources\CustomerResource; | ||||
| use Crater\Models\Customer; | ||||
| 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) | ||||
|     { | ||||
|         $this->authorize('viewAny', Customer::class); | ||||
|  | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $customers = Customer::with('creator') | ||||
|             ->whereCompany() | ||||
|             ->applyFilters($request->all()) | ||||
|             ->select( | ||||
|                 'customers.*', | ||||
|                 DB::raw('sum(invoices.base_due_amount) as base_due_amount'), | ||||
|                 DB::raw('sum(invoices.due_amount) as due_amount'), | ||||
|             ) | ||||
|             ->groupBy('customers.id') | ||||
|             ->leftJoin('invoices', 'customers.id', '=', 'invoices.customer_id') | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return (CustomerResource::collection($customers)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'customer_total_count' => Customer::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(Requests\CustomerRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Customer::class); | ||||
|  | ||||
|         $customer = Customer::createCustomer($request); | ||||
|  | ||||
|         return new CustomerResource($customer); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  Customer $customer | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Customer $customer) | ||||
|     { | ||||
|         $this->authorize('view', $customer); | ||||
|  | ||||
|         return new CustomerResource($customer); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Crater\Models\Customer $customer | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(Requests\CustomerRequest $request, Customer $customer) | ||||
|     { | ||||
|         $this->authorize('update', $customer); | ||||
|  | ||||
|         $customer = Customer::updateCustomer($request, $customer); | ||||
|  | ||||
|         if (is_string($customer)) { | ||||
|             return respondJson('you_cannot_edit_currency', 'Cannot change currency once transactions created'); | ||||
|         } | ||||
|  | ||||
|         return new CustomerResource($customer); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 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(DeleteCustomersRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple customers'); | ||||
|  | ||||
|         Customer::deleteCustomers($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										165
									
								
								app/Http/Controllers/V1/Admin/Dashboard/DashboardController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								app/Http/Controllers/V1/Admin/Dashboard/DashboardController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,165 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Dashboard; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Customer; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Expense; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class DashboardController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $company = Company::find($request->header('company')); | ||||
|  | ||||
|         $this->authorize('view dashboard', $company); | ||||
|  | ||||
|         $invoice_totals = []; | ||||
|         $expense_totals = []; | ||||
|         $receipt_totals = []; | ||||
|         $net_income_totals = []; | ||||
|  | ||||
|         $i = 0; | ||||
|         $months = []; | ||||
|         $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( | ||||
|                 $invoice_totals, | ||||
|                 Invoice::whereBetween( | ||||
|                     'invoice_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                 ->whereCompany() | ||||
|                 ->sum('base_total') | ||||
|             ); | ||||
|             array_push( | ||||
|                 $expense_totals, | ||||
|                 Expense::whereBetween( | ||||
|                     'expense_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                 ->whereCompany() | ||||
|                 ->sum('base_amount') | ||||
|             ); | ||||
|             array_push( | ||||
|                 $receipt_totals, | ||||
|                 Payment::whereBetween( | ||||
|                     'payment_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                 ->whereCompany() | ||||
|                 ->sum('base_amount') | ||||
|             ); | ||||
|             array_push( | ||||
|                 $net_income_totals, | ||||
|                 ($receipt_totals[$i] - $expense_totals[$i]) | ||||
|             ); | ||||
|             $i++; | ||||
|             array_push($months, $start->format('M')); | ||||
|             $monthCounter++; | ||||
|             $end->startOfMonth(); | ||||
|             $start->addMonth()->startOfMonth(); | ||||
|             $end->addMonth()->endOfMonth(); | ||||
|         } | ||||
|  | ||||
|         $start->subMonth()->endOfMonth(); | ||||
|  | ||||
|         $total_sales = Invoice::whereBetween( | ||||
|             'invoice_date', | ||||
|             [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|         ) | ||||
|             ->whereCompany() | ||||
|             ->sum('base_total'); | ||||
|  | ||||
|         $total_receipts = Payment::whereBetween( | ||||
|             'payment_date', | ||||
|             [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|         ) | ||||
|             ->whereCompany() | ||||
|             ->sum('base_amount'); | ||||
|  | ||||
|         $total_expenses = Expense::whereBetween( | ||||
|             'expense_date', | ||||
|             [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|         ) | ||||
|             ->whereCompany() | ||||
|             ->sum('base_amount'); | ||||
|  | ||||
|         $total_net_income = (int)$total_receipts - (int)$total_expenses; | ||||
|  | ||||
|         $chart_data = [ | ||||
|             'months' => $months, | ||||
|             'invoice_totals' => $invoice_totals, | ||||
|             'expense_totals' => $expense_totals, | ||||
|             'receipt_totals' => $receipt_totals, | ||||
|             'net_income_totals' => $net_income_totals, | ||||
|         ]; | ||||
|  | ||||
|         $total_customer_count = Customer::whereCompany()->count(); | ||||
|         $total_invoice_count = Invoice::whereCompany() | ||||
|             ->count(); | ||||
|         $total_estimate_count = Estimate::whereCompany()->count(); | ||||
|         $total_amount_due = Invoice::whereCompany() | ||||
|             ->sum('base_due_amount'); | ||||
|  | ||||
|         $recent_due_invoices = Invoice::with('customer') | ||||
|             ->whereCompany() | ||||
|             ->where('base_due_amount', '>', 0) | ||||
|             ->take(5) | ||||
|             ->latest() | ||||
|             ->get(); | ||||
|         $recent_estimates = Estimate::with('customer')->whereCompany()->take(5)->latest()->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'total_amount_due' => $total_amount_due, | ||||
|             'total_customer_count' => $total_customer_count, | ||||
|             'total_invoice_count' => $total_invoice_count, | ||||
|             'total_estimate_count' => $total_estimate_count, | ||||
|  | ||||
|             'recent_due_invoices' => $recent_due_invoices, | ||||
|             'recent_estimates' => $recent_estimates, | ||||
|  | ||||
|             'chart_data' => $chart_data, | ||||
|  | ||||
|             'total_sales' => $total_sales, | ||||
|             'total_receipts' => $total_receipts, | ||||
|             'total_expenses' => $total_expenses, | ||||
|             'total_net_income' => $total_net_income, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Estimate; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Estimate; | ||||
| @ -17,6 +17,8 @@ class ChangeEstimateStatusController extends Controller | ||||
|     */ | ||||
|     public function __invoke(Request $request, Estimate $estimate) | ||||
|     { | ||||
|         $this->authorize('send estimate', $estimate); | ||||
| 
 | ||||
|         $estimate->update($request->only('status')); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -0,0 +1,132 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Estimate; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\InvoiceResource; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Services\SerialNumberFormatter; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| use Vinkla\Hashids\Facades\Hashids; | ||||
|  | ||||
| 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, Invoice $invoice) | ||||
|     { | ||||
|         $this->authorize('create', Invoice::class); | ||||
|  | ||||
|         $estimate->load(['items', 'items.taxes', 'customer', 'taxes']); | ||||
|  | ||||
|         $invoice_date = Carbon::now(); | ||||
|         $due_date = null; | ||||
|  | ||||
|         $dueDateEnabled = CompanySetting::getSetting( | ||||
|             'invoice_set_due_date_automatically', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         if ($dueDateEnabled === 'YES') { | ||||
|             $dueDateDays = CompanySetting::getSetting( | ||||
|                 'invoice_due_date_days', | ||||
|                 $request->header('company') | ||||
|             ); | ||||
|             $due_date = Carbon::now()->addDays($dueDateDays)->format('Y-m-d'); | ||||
|         } | ||||
|  | ||||
|         $serial = (new SerialNumberFormatter()) | ||||
|             ->setModel($invoice) | ||||
|             ->setCompany($estimate->company_id) | ||||
|             ->setCustomer($estimate->customer_id) | ||||
|             ->setNextNumbers(); | ||||
|  | ||||
|         $templateName = $estimate->getInvoiceTemplateName(); | ||||
|  | ||||
|         $exchange_rate = $estimate->exchange_rate; | ||||
|  | ||||
|         $invoice = Invoice::create([ | ||||
|             'creator_id' => Auth::id(), | ||||
|             'invoice_date' => $invoice_date->format('Y-m-d'), | ||||
|             'due_date' => $due_date, | ||||
|             'invoice_number' => $serial->getNextNumber(), | ||||
|             'sequence_number' => $serial->nextSequenceNumber, | ||||
|             'customer_sequence_number' => $serial->nextCustomerSequenceNumber, | ||||
|             'reference_number' => $serial->getNextNumber(), | ||||
|             'customer_id' => $estimate->customer_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'template_name' => $templateName, | ||||
|             '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, | ||||
|             'exchange_rate' => $exchange_rate, | ||||
|             'base_discount_val' => $estimate->discount_val * $exchange_rate, | ||||
|             'base_sub_total' => $estimate->sub_total * $exchange_rate, | ||||
|             'base_total' => $estimate->total * $exchange_rate, | ||||
|             'base_tax' => $estimate->tax * $exchange_rate, | ||||
|             'currency_id' => $estimate->currency_id, | ||||
|         ]); | ||||
|  | ||||
|         $invoice->unique_hash = Hashids::connection(Invoice::class)->encode($invoice->id); | ||||
|         $invoice->save(); | ||||
|         $invoiceItems = $estimate->items->toArray(); | ||||
|  | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $invoiceItem['name'] = $invoiceItem['name']; | ||||
|             $estimateItem['exchange_rate'] = $exchange_rate; | ||||
|             $estimateItem['base_price'] = $invoiceItem['price'] * $exchange_rate; | ||||
|             $estimateItem['base_discount_val'] = $invoiceItem['discount_val'] * $exchange_rate; | ||||
|             $estimateItem['base_tax'] = $invoiceItem['tax'] * $exchange_rate; | ||||
|             $estimateItem['base_total'] = $invoiceItem['total'] * $exchange_rate; | ||||
|  | ||||
|             $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'); | ||||
|                 $tax['exchange_rate'] = $exchange_rate; | ||||
|                 $tax['base_amount'] = $tax['amount'] * $exchange_rate; | ||||
|                 $tax['currency_id'] = $estimate->currency_id; | ||||
|                 unset($tax['estimate_id']); | ||||
|  | ||||
|                 $invoice->taxes()->create($tax); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $estimate->checkForEstimateConvertAction(); | ||||
|  | ||||
|         $invoice = Invoice::find($invoice->id); | ||||
|  | ||||
|         return new InvoiceResource($invoice); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Estimate; | ||||
| 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) | ||||
|     { | ||||
|         $this->authorize('viewAny', Estimate::class); | ||||
|  | ||||
|         $estimateTemplates = Estimate::estimateTemplates(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'estimateTemplates' => $estimateTemplates | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,77 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeleteEstimatesRequest; | ||||
| use Crater\Http\Requests\EstimatesRequest; | ||||
| use Crater\Http\Resources\EstimateResource; | ||||
| use Crater\Jobs\GenerateEstimatePdfJob; | ||||
| use Crater\Models\Estimate; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class EstimatesController extends Controller | ||||
| { | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Estimate::class); | ||||
|  | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $estimates = Estimate::whereCompany() | ||||
|             ->join('customers', 'customers.id', '=', 'estimates.customer_id') | ||||
|             ->applyFilters($request->all()) | ||||
|             ->select('estimates.*', 'customers.name') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return (EstimateResource::collection($estimates)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'estimate_total_count' => Estimate::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
|  | ||||
|     public function store(EstimatesRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Estimate::class); | ||||
|  | ||||
|         $estimate = Estimate::createEstimate($request); | ||||
|  | ||||
|         if ($request->has('estimateSend')) { | ||||
|             $estimate->send($request->title, $request->body); | ||||
|         } | ||||
|  | ||||
|         GenerateEstimatePdfJob::dispatch($estimate); | ||||
|  | ||||
|         return new EstimateResource($estimate); | ||||
|     } | ||||
|  | ||||
|     public function show(Request $request, Estimate $estimate) | ||||
|     { | ||||
|         $this->authorize('view', $estimate); | ||||
|  | ||||
|         return new EstimateResource($estimate); | ||||
|     } | ||||
|  | ||||
|     public function update(EstimatesRequest $request, Estimate $estimate) | ||||
|     { | ||||
|         $this->authorize('update', $estimate); | ||||
|  | ||||
|         $estimate = $estimate->updateEstimate($request); | ||||
|  | ||||
|         GenerateEstimatePdfJob::dispatch($estimate, true); | ||||
|  | ||||
|         return new EstimateResource($estimate); | ||||
|     } | ||||
|  | ||||
|     public function delete(DeleteEstimatesRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple estimates'); | ||||
|  | ||||
|         Estimate::destroy($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Estimate; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendEstimatesRequest; | ||||
| @ -16,6 +16,8 @@ class SendEstimateController extends Controller | ||||
|     */ | ||||
|     public function __invoke(SendEstimatesRequest $request, Estimate $estimate) | ||||
|     { | ||||
|         $this->authorize('send estimate', $estimate); | ||||
| 
 | ||||
|         $response = $estimate->send($request->all()); | ||||
| 
 | ||||
|         return response()->json($response); | ||||
| @ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Estimate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendEstimatesRequest; | ||||
| use Crater\Models\Estimate; | ||||
| use Illuminate\Mail\Markdown; | ||||
|  | ||||
| class SendEstimatePreviewController extends Controller | ||||
| { | ||||
|     /** | ||||
|     * Handle the incoming request. | ||||
|     * | ||||
|     * @param  \Crater\Http\Requests\SendEstimatesRequest  $request | ||||
|     * @return \Illuminate\Http\JsonResponse | ||||
|     */ | ||||
|     public function __invoke(SendEstimatesRequest $request, Estimate $estimate) | ||||
|     { | ||||
|         $this->authorize('send estimate', $estimate); | ||||
|  | ||||
|         $markdown = new Markdown(view(), config('mail.markdown')); | ||||
|  | ||||
|         return $markdown->render('emails.send.estimate', ['data' => $estimate->sendEstimateData($request->all())]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,117 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\ExchangeRate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\ExchangeRateProviderRequest; | ||||
| use Crater\Http\Resources\ExchangeRateProviderResource; | ||||
| use Crater\Models\ExchangeRateProvider; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class ExchangeRateProviderController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', ExchangeRateProvider::class); | ||||
|  | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
|  | ||||
|         $exchangeRateProviders = ExchangeRateProvider::whereCompany()->paginate($limit); | ||||
|  | ||||
|         return ExchangeRateProviderResource::collection($exchangeRateProviders); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(ExchangeRateProviderRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', ExchangeRateProvider::class); | ||||
|  | ||||
|         $query = ExchangeRateProvider::checkActiveCurrencies($request); | ||||
|  | ||||
|         if (count($query) !== 0) { | ||||
|             return respondJson('currency_used', 'Currency used.'); | ||||
|         } | ||||
|  | ||||
|         $checkConverterApi = ExchangeRateProvider::checkExchangeRateProviderStatus($request); | ||||
|  | ||||
|         if ($checkConverterApi->status() == 200) { | ||||
|             $exchangeRateProvider = ExchangeRateProvider::createFromRequest($request); | ||||
|  | ||||
|             return new ExchangeRateProviderResource($exchangeRateProvider); | ||||
|         } | ||||
|  | ||||
|         return $checkConverterApi; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\ExchangeRateProvider  $exchangeRateProvider | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(ExchangeRateProvider $exchangeRateProvider) | ||||
|     { | ||||
|         $this->authorize('view', $exchangeRateProvider); | ||||
|  | ||||
|         return new ExchangeRateProviderResource($exchangeRateProvider); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Crater\Models\ExchangeRateProvider  $exchangeRateProvider | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(ExchangeRateProviderRequest $request, ExchangeRateProvider $exchangeRateProvider) | ||||
|     { | ||||
|         $this->authorize('update', $exchangeRateProvider); | ||||
|  | ||||
|         $query = $exchangeRateProvider->checkUpdateActiveCurrencies($request); | ||||
|  | ||||
|         if (count($query) !== 0) { | ||||
|             return respondJson('currency_used', 'Currency used.'); | ||||
|         } | ||||
|  | ||||
|         $checkConverterApi = ExchangeRateProvider::checkExchangeRateProviderStatus($request); | ||||
|  | ||||
|         if ($checkConverterApi->status() == 200) { | ||||
|             $exchangeRateProvider->updateFromRequest($request); | ||||
|  | ||||
|             return new ExchangeRateProviderResource($exchangeRateProvider); | ||||
|         } | ||||
|  | ||||
|         return $checkConverterApi; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\Models\ExchangeRateProvider  $exchangeRateProvider | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(ExchangeRateProvider $exchangeRateProvider) | ||||
|     { | ||||
|         $this->authorize('delete', $exchangeRateProvider); | ||||
|  | ||||
|         if ($exchangeRateProvider->active == true) { | ||||
|             return respondJson('provider_active', 'Provider Active.'); | ||||
|         } | ||||
|  | ||||
|         $exchangeRateProvider->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,35 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\ExchangeRate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Currency; | ||||
| use Crater\Models\ExchangeRateProvider; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class GetActiveProviderController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request, Currency $currency) | ||||
|     { | ||||
|         $query = ExchangeRateProvider::whereCompany()->whereJsonContains('currencies', $currency->code) | ||||
|                 ->where('active', true) | ||||
|                 ->get(); | ||||
|  | ||||
|         if (count($query) !== 0) { | ||||
|             return response()->json([ | ||||
|                 'success' => true, | ||||
|                 'message' => 'provider_active', | ||||
|             ], 200); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'error' => 'no_active_provider', | ||||
|         ], 200); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\ExchangeRate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Currency; | ||||
| use Crater\Models\ExchangeRateLog; | ||||
| use Crater\Models\ExchangeRateProvider; | ||||
| use Crater\Traits\ExchangeRateProvidersTrait; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Arr; | ||||
|  | ||||
| class GetExchangeRateController extends Controller | ||||
| { | ||||
|     use ExchangeRateProvidersTrait; | ||||
|  | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request, Currency $currency) | ||||
|     { | ||||
|         $settings = CompanySetting::getSettings(['currency'], $request->header('company')); | ||||
|         $baseCurrency = Currency::findOrFail($settings['currency']); | ||||
|  | ||||
|         $query = ExchangeRateProvider::whereJsonContains('currencies', $currency->code) | ||||
|                 ->where('active', true) | ||||
|                 ->get() | ||||
|                 ->toArray(); | ||||
|  | ||||
|         $exchange_rate = ExchangeRateLog::where('base_currency_id', $currency->id) | ||||
|                 ->where('currency_id', $baseCurrency->id) | ||||
|                 ->orderBy('created_at', 'desc') | ||||
|                 ->value('exchange_rate'); | ||||
|  | ||||
|         if ($query) { | ||||
|             $filter = Arr::only($query[0], ['key', 'driver', 'driver_config']); | ||||
|             $exchange_rate_value = $this->getExchangeRate($filter, $currency->code, $baseCurrency->code); | ||||
|  | ||||
|             if ($exchange_rate_value->status() == 200) { | ||||
|                 return $exchange_rate_value; | ||||
|             } | ||||
|         } | ||||
|         if ($exchange_rate) { | ||||
|             return response()->json([ | ||||
|                 'exchangeRate' => [$exchange_rate], | ||||
|             ], 200); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'error' => 'no_exchange_rate_available', | ||||
|         ], 200); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\ExchangeRate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\ExchangeRateProvider; | ||||
| use Crater\Traits\ExchangeRateProvidersTrait; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class GetSupportedCurrenciesController extends Controller | ||||
| { | ||||
|     use ExchangeRateProvidersTrait; | ||||
|  | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', ExchangeRateProvider::class); | ||||
|  | ||||
|         return $this->getSupportedCurrencies($request); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,55 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\ExchangeRate; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\ExchangeRateProvider; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class GetUsedCurrenciesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', ExchangeRateProvider::class); | ||||
|  | ||||
|         $providerId = $request->provider_id; | ||||
|  | ||||
|         $activeExchangeRateProviders = ExchangeRateProvider::where('active', true) | ||||
|             ->whereCompany() | ||||
|             ->when($providerId, function ($query) use ($providerId) { | ||||
|                 return $query->where('id', '<>', $providerId); | ||||
|             }) | ||||
|             ->pluck('currencies'); | ||||
|         $activeExchangeRateProvider = []; | ||||
|  | ||||
|         foreach ($activeExchangeRateProviders as $data) { | ||||
|             if (is_array($data)) { | ||||
|                 for ($limit = 0; $limit < count($data); $limit++) { | ||||
|                     $activeExchangeRateProvider[] = $data[$limit]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $allExchangeRateProviders = ExchangeRateProvider::whereCompany()->pluck('currencies'); | ||||
|         $allExchangeRateProvider = []; | ||||
|  | ||||
|         foreach ($allExchangeRateProviders as $data) { | ||||
|             if (is_array($data)) { | ||||
|                 for ($limit = 0; $limit < count($data); $limit++) { | ||||
|                     $allExchangeRateProvider[] = $data[$limit]; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'allUsedCurrencies' => $allExchangeRateProvider ? $allExchangeRateProvider : [], | ||||
|             'activeUsedCurrencies' => $activeExchangeRateProvider ? $activeExchangeRateProvider : [], | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Expense; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\ExpenseCategoryRequest; | ||||
| use Crater\Http\Resources\ExpenseCategoryResource; | ||||
| use Crater\Models\ExpenseCategory; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,19 +17,16 @@ class ExpenseCategoriesController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', ExpenseCategory::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
| 
 | ||||
|         $categories = ExpenseCategory::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'category_id', | ||||
|                 'search', | ||||
|             ])) | ||||
|         $categories = ExpenseCategory::applyFilters($request->all()) | ||||
|             ->whereCompany() | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'categories' => $categories, | ||||
|         ]); | ||||
|         return ExpenseCategoryResource::collection($categories); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -39,14 +37,11 @@ class ExpenseCategoriesController extends Controller | ||||
|      */ | ||||
|     public function store(ExpenseCategoryRequest $request) | ||||
|     { | ||||
|         $data = $request->validated(); | ||||
|         $data['company_id'] = $request->header('company'); | ||||
|         $category = ExpenseCategory::create($data); | ||||
|         $this->authorize('create', ExpenseCategory::class); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         $category = ExpenseCategory::create($request->getExpenseCategoryPayload()); | ||||
| 
 | ||||
|         return new ExpenseCategoryResource($category); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -57,9 +52,9 @@ class ExpenseCategoriesController extends Controller | ||||
|      */ | ||||
|     public function show(ExpenseCategory $category) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|         ]); | ||||
|         $this->authorize('view', $category); | ||||
| 
 | ||||
|         return new ExpenseCategoryResource($category); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -71,12 +66,11 @@ class ExpenseCategoriesController extends Controller | ||||
|      */ | ||||
|     public function update(ExpenseCategoryRequest $request, ExpenseCategory $category) | ||||
|     { | ||||
|         $category->update($request->validated()); | ||||
|         $this->authorize('update', $category); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'category' => $category, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         $category->update($request->getExpenseCategoryPayload()); | ||||
| 
 | ||||
|         return new ExpenseCategoryResource($category); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -87,10 +81,10 @@ class ExpenseCategoriesController extends Controller | ||||
|      */ | ||||
|     public function destroy(ExpenseCategory $category) | ||||
|     { | ||||
|         $this->authorize('delete', $category); | ||||
| 
 | ||||
|         if ($category->expenses() && $category->expenses()->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|             ]); | ||||
|             return respondJson('expense_attached', 'Expense Attached'); | ||||
|         } | ||||
| 
 | ||||
|         $category->delete(); | ||||
| @ -1,10 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Expense; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeleteExpensesRequest; | ||||
| use Crater\Http\Requests\ExpenseRequest; | ||||
| use Crater\Http\Resources\ExpenseResource; | ||||
| use Crater\Models\Expense; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -17,29 +18,22 @@ class ExpensesController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Expense::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
| 
 | ||||
|         $expenses = Expense::with('category', 'creator', 'fields') | ||||
|             ->leftJoin('users', 'users.id', '=', 'expenses.user_id') | ||||
|             ->whereCompany() | ||||
|             ->leftJoin('customers', 'customers.id', '=', 'expenses.customer_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') | ||||
|             ->applyFilters($request->all()) | ||||
|             ->select('expenses.*', 'expense_categories.name', 'customers.name as user_name') | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'expenses' => $expenses, | ||||
|             'expenseTotalCount' => Expense::count(), | ||||
|         ]); | ||||
|         return (ExpenseResource::collection($expenses)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'expense_total_count' => Expense::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -50,12 +44,11 @@ class ExpensesController extends Controller | ||||
|      */ | ||||
|     public function store(ExpenseRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Expense::class); | ||||
| 
 | ||||
|         $expense = Expense::createExpense($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new ExpenseResource($expense); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -66,11 +59,9 @@ class ExpensesController extends Controller | ||||
|      */ | ||||
|     public function show(Expense $expense) | ||||
|     { | ||||
|         $expense->load('creator', 'fields.customField'); | ||||
|         $this->authorize('view', $expense); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|         ]); | ||||
|         return new ExpenseResource($expense); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -82,16 +73,17 @@ class ExpensesController extends Controller | ||||
|      */ | ||||
|     public function update(ExpenseRequest $request, Expense $expense) | ||||
|     { | ||||
|         $this->authorize('update', $expense); | ||||
| 
 | ||||
|         $expense->updateExpense($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'expense' => $expense, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new ExpenseResource($expense); | ||||
|     } | ||||
| 
 | ||||
|     public function delete(DeleteExpensesRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple expenses'); | ||||
| 
 | ||||
|         Expense::destroy($request->ids); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -0,0 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\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) | ||||
|     { | ||||
|         $this->authorize('view', $expense); | ||||
|  | ||||
|         if ($expense) { | ||||
|             $media = $expense->getFirstMedia('receipts'); | ||||
|  | ||||
|             if ($media) { | ||||
|                 return response()->file($media->getPath()); | ||||
|             } | ||||
|  | ||||
|             return respondJson('receipt_does_not_exist', 'Receipt does not exist.'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Expense; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Expense; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Expense; | ||||
| @ -17,6 +17,8 @@ class UploadReceiptController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request, Expense $expense) | ||||
|     { | ||||
|         $this->authorize('update', $expense); | ||||
| 
 | ||||
|         $data = json_decode($request->attachment_receipt); | ||||
| 
 | ||||
|         if ($data) { | ||||
| @ -26,11 +28,11 @@ class UploadReceiptController extends Controller | ||||
| 
 | ||||
|             $expense->addMediaFromBase64($data->data) | ||||
|                 ->usingFileName($data->name) | ||||
|                 ->toMediaCollection('receipts', 'local'); | ||||
|                 ->toMediaCollection('receipts'); | ||||
|         } | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'success' => 'Expense receipts uploaded successfully', | ||||
|         ]); | ||||
|         ], 200); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,63 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\CompanyResource; | ||||
| use Crater\Http\Resources\UserResource; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Currency; | ||||
| use Crater\Traits\GeneratesMenuTrait; | ||||
| use Illuminate\Http\Request; | ||||
| use Silber\Bouncer\BouncerFacade; | ||||
|  | ||||
| class BootstrapController extends Controller | ||||
| { | ||||
|     use GeneratesMenuTrait; | ||||
|  | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $current_user = $request->user(); | ||||
|         $current_user_settings = $current_user->getAllSettings(); | ||||
|  | ||||
|         $main_menu = $this->generateMenu('main_menu', $current_user); | ||||
|  | ||||
|         $setting_menu = $this->generateMenu('setting_menu', $current_user); | ||||
|  | ||||
|         $companies = $current_user->companies; | ||||
|  | ||||
|         $current_company = Company::find($request->header('company')); | ||||
|  | ||||
|         if ((! $current_company) || ($current_company && ! $current_user->hasCompany($current_company->id))) { | ||||
|             $current_company = $current_user->companies()->first(); | ||||
|         } | ||||
|  | ||||
|         $current_company_settings = CompanySetting::getAllSettings($current_company->id); | ||||
|  | ||||
|         $current_company_currency = $current_company_settings->has('currency') | ||||
|             ? Currency::find($current_company_settings->get('currency')) | ||||
|             : Currency::first(); | ||||
|  | ||||
|         BouncerFacade::refreshFor($current_user); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'current_user' => new UserResource($current_user), | ||||
|             'current_user_settings' => $current_user_settings, | ||||
|             'current_user_abilities' => $current_user->getAbilities(), | ||||
|             'companies' => CompanyResource::collection($companies), | ||||
|             'current_company' => new CompanyResource($current_company), | ||||
|             'current_company_settings' => $current_company_settings, | ||||
|             'current_company_currency' => $current_company_currency, | ||||
|             'config' => config('crater'), | ||||
|             'main_menu' => $main_menu, | ||||
|             'setting_menu' => $setting_menu, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,128 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\BulkExchangeRateRequest; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Crater\Models\Tax; | ||||
|  | ||||
| class BulkExchangeRateController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(BulkExchangeRateRequest $request) | ||||
|     { | ||||
|         $bulkExchangeRate = CompanySetting::getSetting('bulk_exchange_rate_configured', $request->header('company')); | ||||
|  | ||||
|         if ($bulkExchangeRate == 'NO') { | ||||
|             if ($request->currencies) { | ||||
|                 foreach ($request->currencies as $currency) { | ||||
|                     $currency['exchange_rate'] = $currency['exchange_rate'] ?? 1; | ||||
|  | ||||
|                     $invoices = Invoice::where('currency_id', $currency['id'])->get(); | ||||
|  | ||||
|                     if ($invoices) { | ||||
|                         foreach ($invoices as $invoice) { | ||||
|                             $invoice->update([ | ||||
|                                 'exchange_rate' => $currency['exchange_rate'], | ||||
|                                 'base_discount_val' => $invoice->sub_total * $currency['exchange_rate'], | ||||
|                                 'base_sub_total' => $invoice->sub_total * $currency['exchange_rate'], | ||||
|                                 'base_total' => $invoice->total * $currency['exchange_rate'], | ||||
|                                 'base_tax' => $invoice->tax * $currency['exchange_rate'], | ||||
|                                 'base_due_amount' => $invoice->due_amount * $currency['exchange_rate'] | ||||
|                             ]); | ||||
|  | ||||
|                             $this->items($invoice); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     $estimates = Estimate::where('currency_id', $currency['id'])->get(); | ||||
|  | ||||
|                     if ($estimates) { | ||||
|                         foreach ($estimates as $estimate) { | ||||
|                             $estimate->update([ | ||||
|                                 'exchange_rate' => $currency['exchange_rate'], | ||||
|                                 'base_discount_val' => $estimate->sub_total * $currency['exchange_rate'], | ||||
|                                 'base_sub_total' => $estimate->sub_total * $currency['exchange_rate'], | ||||
|                                 'base_total' => $estimate->total * $currency['exchange_rate'], | ||||
|                                 'base_tax' => $estimate->tax * $currency['exchange_rate'] | ||||
|                             ]); | ||||
|  | ||||
|                             $this->items($estimate); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     $taxes = Tax::where('currency_id', $currency['id'])->get(); | ||||
|  | ||||
|                     if ($taxes) { | ||||
|                         foreach ($taxes as $tax) { | ||||
|                             $tax->base_amount = $tax->base_amount * $currency['exchange_rate']; | ||||
|                             $tax->save(); | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     $payments = Payment::where('currency_id', $currency['id'])->get(); | ||||
|  | ||||
|                     if ($payments) { | ||||
|                         foreach ($payments as $payment) { | ||||
|                             $payment->exchange_rate = $currency['exchange_rate']; | ||||
|                             $payment->base_amount = $payment->amount * $currency['exchange_rate']; | ||||
|                             $payment->save(); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             $settings = [ | ||||
|                 'bulk_exchange_rate_configured' => 'YES' | ||||
|             ]; | ||||
|  | ||||
|             CompanySetting::setSettings($settings, $request->header('company')); | ||||
|  | ||||
|             return response()->json([ | ||||
|                 'success' => true | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'error' => false | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     public function items($model) | ||||
|     { | ||||
|         foreach ($model->items as $item) { | ||||
|             $item->update([ | ||||
|                 'exchange_rate' => $model->exchange_rate, | ||||
|                 'base_discount_val' => $item->discount_val * $model->exchange_rate, | ||||
|                 'base_price' => $item->price * $model->exchange_rate, | ||||
|                 'base_tax' => $item->tax * $model->exchange_rate, | ||||
|                 'base_total' => $item->total * $model->exchange_rate | ||||
|             ]); | ||||
|  | ||||
|             $this->taxes($item); | ||||
|         } | ||||
|  | ||||
|         $this->taxes($model); | ||||
|     } | ||||
|  | ||||
|     public function taxes($model) | ||||
|     { | ||||
|         if ($model->taxes()->exists()) { | ||||
|             $model->taxes->map(function ($tax) use ($model) { | ||||
|                 $tax->update([ | ||||
|                     'exchange_rate' => $model->exchange_rate, | ||||
|                     'base_amount' => $tax->amount * $model->exchange_rate, | ||||
|                 ]); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,12 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Estimate; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\EstimateTemplate; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| class EstimateTemplatesController extends Controller | ||||
| class ConfigController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
| @ -17,7 +16,7 @@ class EstimateTemplatesController extends Controller | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'templates' => EstimateTemplate::all(), | ||||
|             $request->key => config('crater.'.$request->key), | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,8 +1,9 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\CountryResource; | ||||
| use Crater\Models\Country; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,8 +17,8 @@ class CountriesController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'countries' => Country::all(), | ||||
|         ]); | ||||
|         $countries = Country::all(); | ||||
| 
 | ||||
|         return CountryResource::collection($countries); | ||||
|     } | ||||
| } | ||||
| @ -1,8 +1,9 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\CurrencyResource; | ||||
| use Crater\Models\Currency; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -18,8 +19,6 @@ class CurrenciesController extends Controller | ||||
|     { | ||||
|         $currencies = Currency::latest()->get(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'currencies' => $currencies, | ||||
|         ]); | ||||
|         return CurrencyResource::collection($currencies); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\DateFormatter; | ||||
| @ -0,0 +1,37 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Currency; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Crater\Models\Tax; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class GetAllUsedCurrenciesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $invoices = Invoice::where('exchange_rate', null)->pluck('currency_id')->toArray(); | ||||
|  | ||||
|         $taxes = Tax::where('exchange_rate', null)->pluck('currency_id')->toArray(); | ||||
|  | ||||
|         $estimates = Estimate::where('exchange_rate', null)->pluck('currency_id')->toArray(); | ||||
|  | ||||
|         $payments = Payment::where('exchange_rate', null)->pluck('currency_id')->toArray(); | ||||
|  | ||||
|         $currencies = array_merge($invoices, $taxes, $estimates, $payments); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'currencies' => Currency::whereIn('id', $currencies)->get() | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,66 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\Payment; | ||||
| use Crater\Services\SerialNumberFormatter; | ||||
| 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, Invoice $invoice, Estimate $estimate, Payment $payment) | ||||
|     { | ||||
|         $key = $request->key; | ||||
|         $nextNumber = null; | ||||
|         $serial = (new SerialNumberFormatter()) | ||||
|             ->setCompany($request->header('company')) | ||||
|             ->setCustomer($request->userId); | ||||
|  | ||||
|         try { | ||||
|             switch ($key) { | ||||
|                 case 'invoice': | ||||
|                     $nextNumber = $serial->setModel($invoice) | ||||
|                         ->setModelObject($request->model_id) | ||||
|                         ->getNextNumber(); | ||||
|  | ||||
|                     break; | ||||
|  | ||||
|                 case 'estimate': | ||||
|                     $nextNumber = $serial->setModel($estimate) | ||||
|                         ->setModelObject($request->model_id) | ||||
|                         ->getNextNumber(); | ||||
|  | ||||
|                     break; | ||||
|  | ||||
|                 case 'payment': | ||||
|                     $nextNumber = $serial->setModel($payment) | ||||
|                         ->setModelObject($request->model_id) | ||||
|                         ->getNextNumber(); | ||||
|  | ||||
|                     break; | ||||
|  | ||||
|                 default: | ||||
|                     return; | ||||
|             } | ||||
|         } catch (\Exception $exception) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => $exception->getMessage() | ||||
|             ]); | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|             'nextNumber' => $nextNumber, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\NotesRequest; | ||||
| use Crater\Http\Resources\NoteResource; | ||||
| use Crater\Models\Note; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,15 +17,16 @@ class NotesController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('view notes'); | ||||
| 
 | ||||
|         $limit = $request->limit ?? 10; | ||||
| 
 | ||||
|         $notes = Note::latest() | ||||
|             ->applyFilters($request->only(['type', 'search'])) | ||||
|             ->whereCompany() | ||||
|             ->applyFilters($request->all()) | ||||
|             ->paginate($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'notes' => $notes, | ||||
|         ]); | ||||
|         return NoteResource::collection($notes); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -35,11 +37,11 @@ class NotesController extends Controller | ||||
|      */ | ||||
|     public function store(NotesRequest $request) | ||||
|     { | ||||
|         $note = Note::create($request->validated()); | ||||
|         $this->authorize('manage notes'); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'note' => $note, | ||||
|         ]); | ||||
|         $note = Note::create($request->getNotesPayload()); | ||||
| 
 | ||||
|         return new NoteResource($note); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -50,9 +52,9 @@ class NotesController extends Controller | ||||
|      */ | ||||
|     public function show(Note $note) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'note' => $note, | ||||
|         ]); | ||||
|         $this->authorize('view notes'); | ||||
| 
 | ||||
|         return new NoteResource($note); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -64,11 +66,11 @@ class NotesController extends Controller | ||||
|      */ | ||||
|     public function update(NotesRequest $request, Note $note) | ||||
|     { | ||||
|         $note->update($request->validated()); | ||||
|         $this->authorize('manage notes'); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'note' => $note, | ||||
|         ]); | ||||
|         $note->update($request->getNotesPayload()); | ||||
| 
 | ||||
|         return new NoteResource($note); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -79,6 +81,8 @@ class NotesController extends Controller | ||||
|      */ | ||||
|     public function destroy(Note $note) | ||||
|     { | ||||
|         $this->authorize('manage notes'); | ||||
| 
 | ||||
|         $note->delete(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -0,0 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Services\SerialNumberFormatter; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class NumberPlaceholdersController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ($request->format) { | ||||
|             $placeholders = SerialNumberFormatter::getPlaceholders($request->format); | ||||
|         } else { | ||||
|             $placeholders = []; | ||||
|         } | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|             'placeholders' => $placeholders, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,11 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Customer; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| 
 | ||||
| class SearchController extends Controller | ||||
| { | ||||
| @ -17,14 +17,14 @@ class SearchController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $customers = User::where('role', 'customer') | ||||
|             ->applyFilters($request->only(['search'])) | ||||
|         $user = $request->user(); | ||||
| 
 | ||||
|         $customers = Customer::applyFilters($request->only(['search'])) | ||||
|             ->latest() | ||||
|             ->paginate(10); | ||||
| 
 | ||||
|         if (Auth::user()->role == 'super admin') { | ||||
|             $users = User::where('role', 'admin') | ||||
|                 ->applyFilters($request->only(['search'])) | ||||
|         if ($user->isOwner()) { | ||||
|             $users = User::applyFilters($request->only(['search'])) | ||||
|                 ->latest() | ||||
|                 ->paginate(10); | ||||
|         } | ||||
| @ -0,0 +1,27 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class SearchUsersController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $this->authorize('create', User::class); | ||||
|  | ||||
|         $users = User::whereEmail($request->email) | ||||
|             ->latest() | ||||
|             ->paginate(10); | ||||
|  | ||||
|         return response()->json(['users' => $users]); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\General; | ||||
| namespace Crater\Http\Controllers\V1\Admin\General; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\TimeZones; | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Invoice; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Invoice; | ||||
| @ -16,6 +16,8 @@ class ChangeInvoiceStatusController extends Controller | ||||
|     */ | ||||
|     public function __invoke(Request $request, Invoice $invoice) | ||||
|     { | ||||
|         $this->authorize('send invoice', $invoice); | ||||
| 
 | ||||
|         if ($request->status == Invoice::STATUS_SENT) { | ||||
|             $invoice->status = Invoice::STATUS_SENT; | ||||
|             $invoice->sent = true; | ||||
							
								
								
									
										131
									
								
								app/Http/Controllers/V1/Admin/Invoice/CloneInvoiceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								app/Http/Controllers/V1/Admin/Invoice/CloneInvoiceController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,131 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Invoice; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Resources\InvoiceResource; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Services\SerialNumberFormatter; | ||||
| use Illuminate\Http\Request; | ||||
| use Vinkla\Hashids\Facades\Hashids; | ||||
|  | ||||
| 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) | ||||
|     { | ||||
|         $this->authorize('create', Invoice::class); | ||||
|  | ||||
|         $date = Carbon::now(); | ||||
|  | ||||
|         $serial = (new SerialNumberFormatter()) | ||||
|             ->setModel($invoice) | ||||
|             ->setCompany($invoice->company_id) | ||||
|             ->setCustomer($invoice->customer_id) | ||||
|             ->setNextNumbers(); | ||||
|  | ||||
|         $due_date = null; | ||||
|         $dueDateEnabled = CompanySetting::getSetting( | ||||
|             'invoice_set_due_date_automatically', | ||||
|             $request->header('company') | ||||
|         ); | ||||
|  | ||||
|         if ($dueDateEnabled === 'YES') { | ||||
|             $dueDateDays = CompanySetting::getSetting( | ||||
|                 'invoice_due_date_days', | ||||
|                 $request->header('company') | ||||
|             ); | ||||
|             $due_date = Carbon::now()->addDays($dueDateDays)->format('Y-m-d'); | ||||
|         } | ||||
|  | ||||
|         $exchange_rate = $invoice->exchange_rate; | ||||
|  | ||||
|         $newInvoice = Invoice::create([ | ||||
|             'invoice_date' => $date->format('Y-m-d'), | ||||
|             'due_date' => $due_date, | ||||
|             'invoice_number' => $serial->getNextNumber(), | ||||
|             'sequence_number' => $serial->nextSequenceNumber, | ||||
|             'customer_sequence_number' => $serial->nextCustomerSequenceNumber, | ||||
|             'reference_number' => $invoice->reference_number, | ||||
|             'customer_id' => $invoice->customer_id, | ||||
|             'company_id' => $request->header('company'), | ||||
|             'template_name' => $invoice->template_name, | ||||
|             '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, | ||||
|             'exchange_rate' => $exchange_rate, | ||||
|             'base_total' => $invoice->total * $exchange_rate, | ||||
|             'base_discount_val' => $invoice->discount_val * $exchange_rate, | ||||
|             'base_sub_total' => $invoice->sub_total * $exchange_rate, | ||||
|             'base_tax' => $invoice->tax * $exchange_rate, | ||||
|             'base_due_amount' => $invoice->total * $exchange_rate, | ||||
|             'currency_id' => $invoice->currency_id, | ||||
|         ]); | ||||
|  | ||||
|         $newInvoice->unique_hash = Hashids::connection(Invoice::class)->encode($newInvoice->id); | ||||
|         $newInvoice->save(); | ||||
|         $invoice->load('items.taxes'); | ||||
|  | ||||
|         $invoiceItems = $invoice->items->toArray(); | ||||
|  | ||||
|         foreach ($invoiceItems as $invoiceItem) { | ||||
|             $invoiceItem['company_id'] = $request->header('company'); | ||||
|             $invoiceItem['name'] = $invoiceItem['name']; | ||||
|             $invoiceItem['exchange_rate'] = $exchange_rate; | ||||
|             $invoiceItem['base_price'] = $invoiceItem['price'] * $exchange_rate; | ||||
|             $invoiceItem['base_discount_val'] = $invoiceItem['discount_val'] * $exchange_rate; | ||||
|             $invoiceItem['base_tax'] = $invoiceItem['tax'] * $exchange_rate; | ||||
|             $invoiceItem['base_total'] = $invoiceItem['total'] * $exchange_rate; | ||||
|  | ||||
|             $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); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if ($invoice->fields()->exists()) { | ||||
|             $customFields = []; | ||||
|  | ||||
|             foreach ($invoice->fields as $data) { | ||||
|                 $customFields[] = [ | ||||
|                     'id' => $data->custom_field_id, | ||||
|                     'value' => $data->defaultAnswer | ||||
|                 ]; | ||||
|             } | ||||
|  | ||||
|             $newInvoice->addCustomFields($customFields); | ||||
|         } | ||||
|  | ||||
|         return new InvoiceResource($newInvoice); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,9 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Invoice; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\InvoiceTemplate; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| class InvoiceTemplatesController extends Controller | ||||
| @ -16,7 +16,9 @@ class InvoiceTemplatesController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $invoiceTemplates = InvoiceTemplate::all(); | ||||
|         $this->authorize('viewAny', Invoice::class); | ||||
| 
 | ||||
|         $invoiceTemplates = Invoice::invoiceTemplates(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'invoiceTemplates' => $invoiceTemplates, | ||||
| @ -1,10 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Invoice; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Http\Requests\DeleteInvoiceRequest; | ||||
| use Crater\Http\Resources\InvoiceResource; | ||||
| use Crater\Jobs\GenerateInvoicePdfJob; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Http\Request; | ||||
| @ -18,31 +19,21 @@ class InvoicesController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Invoice::class); | ||||
| 
 | ||||
|         $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') | ||||
|         $invoices = Invoice::whereCompany() | ||||
|             ->join('customers', 'customers.id', '=', 'invoices.customer_id') | ||||
|             ->applyFilters($request->all()) | ||||
|             ->select('invoices.*', 'customers.name') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'invoices' => $invoices, | ||||
|             'invoiceTotalCount' => Invoice::count(), | ||||
|         ]); | ||||
|         return (InvoiceResource::collection($invoices)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'invoice_total_count' => Invoice::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -53,6 +44,8 @@ class InvoicesController extends Controller | ||||
|      */ | ||||
|     public function store(Requests\InvoicesRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Invoice::class); | ||||
| 
 | ||||
|         $invoice = Invoice::createInvoice($request); | ||||
| 
 | ||||
|         if ($request->has('invoiceSend')) { | ||||
| @ -61,9 +54,7 @@ class InvoicesController extends Controller | ||||
| 
 | ||||
|         GenerateInvoicePdfJob::dispatch($invoice); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'invoice' => $invoice, | ||||
|         ]); | ||||
|         return new InvoiceResource($invoice); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -72,24 +63,11 @@ class InvoicesController extends Controller | ||||
|      * @param  \Crater\Models\Invoice $invoice | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Invoice $invoice) | ||||
|     public function show(Request $request, Invoice $invoice) | ||||
|     { | ||||
|         $invoice->load([ | ||||
|             'items', | ||||
|             'items.taxes', | ||||
|             'user', | ||||
|             'invoiceTemplate', | ||||
|             'taxes.taxType', | ||||
|             'fields.customField', | ||||
|         ]); | ||||
|         $this->authorize('view', $invoice); | ||||
| 
 | ||||
|         $siteData = [ | ||||
|             'invoice' => $invoice, | ||||
|             'nextInvoiceNumber' => $invoice->getInvoiceNumAttribute(), | ||||
|             'invoicePrefix' => $invoice->getInvoicePrefixAttribute(), | ||||
|         ]; | ||||
| 
 | ||||
|         return response()->json($siteData); | ||||
|         return new InvoiceResource($invoice); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -101,14 +79,17 @@ class InvoicesController extends Controller | ||||
|      */ | ||||
|     public function update(Requests\InvoicesRequest $request, Invoice $invoice) | ||||
|     { | ||||
|         $this->authorize('update', $invoice); | ||||
| 
 | ||||
|         $invoice = $invoice->updateInvoice($request); | ||||
| 
 | ||||
|         if (is_string($invoice)) { | ||||
|             return respondJson($invoice, $invoice); | ||||
|         } | ||||
| 
 | ||||
|         GenerateInvoicePdfJob::dispatch($invoice, true); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'invoice' => $invoice, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new InvoiceResource($invoice); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -119,6 +100,8 @@ class InvoicesController extends Controller | ||||
|      */ | ||||
|     public function delete(DeleteInvoiceRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple invoices'); | ||||
| 
 | ||||
|         Invoice::destroy($request->ids); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Invoice; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Invoice; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendInvoiceRequest; | ||||
| @ -16,6 +16,8 @@ class SendInvoiceController extends Controller | ||||
|      */ | ||||
|     public function __invoke(SendInvoiceRequest $request, Invoice $invoice) | ||||
|     { | ||||
|         $this->authorize('send invoice', $invoice); | ||||
| 
 | ||||
|         $invoice->send($request->all()); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Invoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendInvoiceRequest; | ||||
| use Crater\Models\Invoice; | ||||
| use Illuminate\Mail\Markdown; | ||||
|  | ||||
| class SendInvoicePreviewController 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) | ||||
|     { | ||||
|         $this->authorize('send invoice', $invoice); | ||||
|  | ||||
|         $markdown = new Markdown(view(), config('mail.markdown')); | ||||
|  | ||||
|         return $markdown->render('emails.send.invoice', ['data' => $invoice->sendInvoiceData($request->all())]); | ||||
|     } | ||||
| } | ||||
| @ -1,10 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Item; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Item; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests; | ||||
| use Crater\Http\Requests\DeleteItemsRequest; | ||||
| use Crater\Http\Resources\ItemResource; | ||||
| use Crater\Models\Item; | ||||
| use Crater\Models\TaxType; | ||||
| use Illuminate\Http\Request; | ||||
| @ -19,28 +20,22 @@ class ItemsController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Item::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
| 
 | ||||
|         $items = Item::with(['taxes', 'creator']) | ||||
|         $items = Item::whereCompany() | ||||
|             ->leftJoin('units', 'units.id', '=', 'items.unit_id') | ||||
|             ->applyFilters($request->only([ | ||||
|                 'search', | ||||
|                 'price', | ||||
|                 'unit_id', | ||||
|                 'item_id', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|             ->whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->all()) | ||||
|             ->select('items.*', 'units.name as unit_name') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'items' => $items, | ||||
|             'taxTypes' => TaxType::latest()->get(), | ||||
|             'itemTotalCount' => Item::count(), | ||||
|         ]); | ||||
|         return (ItemResource::collection($items)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'tax_types' => TaxType::whereCompany()->latest()->get(), | ||||
|                 'item_total_count' => Item::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -51,11 +46,11 @@ class ItemsController extends Controller | ||||
|      */ | ||||
|     public function store(Requests\ItemsRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Item::class); | ||||
| 
 | ||||
|         $item = Item::createItem($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|         ]); | ||||
|         return new ItemResource($item); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -66,11 +61,9 @@ class ItemsController extends Controller | ||||
|      */ | ||||
|     public function show(Item $item) | ||||
|     { | ||||
|         $item->load('taxes'); | ||||
|         $this->authorize('view', $item); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|         ]); | ||||
|         return new ItemResource($item); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -82,11 +75,11 @@ class ItemsController extends Controller | ||||
|      */ | ||||
|     public function update(Requests\ItemsRequest $request, Item $item) | ||||
|     { | ||||
|         $this->authorize('update', $item); | ||||
| 
 | ||||
|         $item = $item->updateItem($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'item' => $item, | ||||
|         ]); | ||||
|         return new ItemResource($item); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -97,6 +90,8 @@ class ItemsController extends Controller | ||||
|      */ | ||||
|     public function delete(DeleteItemsRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple items'); | ||||
| 
 | ||||
|         Item::destroy($request->ids); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Item; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Item; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\UnitRequest; | ||||
| use Crater\Http\Resources\UnitResource; | ||||
| use Crater\Models\Unit; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,28 +17,16 @@ class UnitsController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Unit::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
| 
 | ||||
|         $units = Unit::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'unit_id', | ||||
|             ])) | ||||
|         $units = Unit::applyFilters($request->all()) | ||||
|             ->whereCompany() | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'units' => $units, | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Show the form for creating a new resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function create() | ||||
|     { | ||||
|         //
 | ||||
|         return UnitResource::collection($units); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -48,13 +37,11 @@ class UnitsController extends Controller | ||||
|      */ | ||||
|     public function store(UnitRequest $request) | ||||
|     { | ||||
|         $data = $request->validated(); | ||||
|         $data['company_id'] = $request->header('company'); | ||||
|         $unit = Unit::create($data); | ||||
|         $this->authorize('create', Unit::class); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'unit' => $unit, | ||||
|         ]); | ||||
|         $unit = Unit::create($request->getUnitPayload()); | ||||
| 
 | ||||
|         return new UnitResource($unit); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -65,9 +52,9 @@ class UnitsController extends Controller | ||||
|      */ | ||||
|     public function show(Unit $unit) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'unit' => $unit, | ||||
|         ]); | ||||
|         $this->authorize('view', $unit); | ||||
| 
 | ||||
|         return new UnitResource($unit); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -79,11 +66,11 @@ class UnitsController extends Controller | ||||
|      */ | ||||
|     public function update(UnitRequest $request, Unit $unit) | ||||
|     { | ||||
|         $unit->update($request->validated()); | ||||
|         $this->authorize('update', $unit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'unit' => $unit, | ||||
|         ]); | ||||
|         $unit->update($request->getUnitPayload()); | ||||
| 
 | ||||
|         return new UnitResource($unit); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -94,10 +81,10 @@ class UnitsController extends Controller | ||||
|      */ | ||||
|     public function destroy(Unit $unit) | ||||
|     { | ||||
|         $this->authorize('delete', $unit); | ||||
| 
 | ||||
|         if ($unit->items()->exists()) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'items_attached', | ||||
|             ]); | ||||
|             return respondJson('items_attached', 'Items Attached'); | ||||
|         } | ||||
| 
 | ||||
|         $unit->delete(); | ||||
| @ -1,23 +1,19 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Mobile; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Mobile; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\LoginRequest; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| use Illuminate\Support\Facades\Hash; | ||||
| use Illuminate\Validation\ValidationException; | ||||
| 
 | ||||
| class AuthController extends Controller | ||||
| { | ||||
|     public function login(Request $request) | ||||
|     public function login(LoginRequest $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)) { | ||||
| @ -40,4 +36,9 @@ class AuthController extends Controller | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| 
 | ||||
|     public function check() | ||||
|     { | ||||
|         return Auth::check(); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Payment; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\PaymentMethodRequest; | ||||
| use Crater\Http\Resources\PaymentMethodResource; | ||||
| use Crater\Models\PaymentMethod; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,19 +17,16 @@ class PaymentMethodsController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', PaymentMethod::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
| 
 | ||||
|         $paymentMethods = PaymentMethod::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'method_id', | ||||
|                 'search', | ||||
|             ])) | ||||
|         $paymentMethods = PaymentMethod::applyFilters($request->all()) | ||||
|             ->whereCompany() | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'paymentMethods' => $paymentMethods, | ||||
|         ]); | ||||
|         return PaymentMethodResource::collection($paymentMethods); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -39,11 +37,11 @@ class PaymentMethodsController extends Controller | ||||
|      */ | ||||
|     public function store(PaymentMethodRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', PaymentMethod::class); | ||||
| 
 | ||||
|         $paymentMethod = PaymentMethod::createPaymentMethod($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'paymentMethod' => $paymentMethod, | ||||
|         ]); | ||||
|         return new PaymentMethodResource($paymentMethod); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -54,9 +52,9 @@ class PaymentMethodsController extends Controller | ||||
|      */ | ||||
|     public function show(PaymentMethod $paymentMethod) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'paymentMethod' => $paymentMethod, | ||||
|         ]); | ||||
|         $this->authorize('view', $paymentMethod); | ||||
| 
 | ||||
|         return new PaymentMethodResource($paymentMethod); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -68,11 +66,11 @@ class PaymentMethodsController extends Controller | ||||
|      */ | ||||
|     public function update(PaymentMethodRequest $request, PaymentMethod $paymentMethod) | ||||
|     { | ||||
|         $this->authorize('update', $paymentMethod); | ||||
| 
 | ||||
|         $paymentMethod->update($request->validated()); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'paymentMethod' => $paymentMethod, | ||||
|         ]); | ||||
|         return new PaymentMethodResource($paymentMethod); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -83,12 +81,12 @@ class PaymentMethodsController extends Controller | ||||
|      */ | ||||
|     public function destroy(PaymentMethod $paymentMethod) | ||||
|     { | ||||
|         $this->authorize('delete', $paymentMethod); | ||||
| 
 | ||||
|         $payments = $paymentMethod->payments; | ||||
| 
 | ||||
|         if ($payments->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'error' => 'payments_attached', | ||||
|             ]); | ||||
|             return respondJson('payments_attached', 'Payments Attached.'); | ||||
|         } | ||||
| 
 | ||||
|         $paymentMethod->delete(); | ||||
| @ -1,10 +1,11 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Payment; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeletePaymentsRequest; | ||||
| use Crater\Http\Requests\PaymentRequest; | ||||
| use Crater\Http\Resources\PaymentResource; | ||||
| use Crater\Models\Payment; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -17,30 +18,23 @@ class PaymentsController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Payment::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
| 
 | ||||
|         $payments = Payment::with(['user', 'invoice', 'paymentMethod', 'creator']) | ||||
|             ->join('users', 'users.id', '=', 'payments.user_id') | ||||
|         $payments = Payment::whereCompany() | ||||
|             ->join('customers', 'customers.id', '=', 'payments.customer_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') | ||||
|             ->applyFilters($request->all()) | ||||
|             ->select('payments.*', 'customers.name', 'invoices.invoice_number', 'payment_methods.name as payment_mode') | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'payments' => $payments, | ||||
|             'paymentTotalCount' => Payment::count(), | ||||
|         ]); | ||||
|         return (PaymentResource::collection($payments)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'payment_total_count' => Payment::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -51,42 +45,33 @@ class PaymentsController extends Controller | ||||
|      */ | ||||
|     public function store(PaymentRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Payment::class); | ||||
| 
 | ||||
|         $payment = Payment::createPayment($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'payment' => $payment, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new PaymentResource($payment); | ||||
|     } | ||||
| 
 | ||||
|     public function show(Request $request, Payment $payment) | ||||
|     { | ||||
|         $payment->load([ | ||||
|             'user', | ||||
|             'invoice', | ||||
|             'paymentMethod', | ||||
|             'fields.customField', | ||||
|         ]); | ||||
|         $this->authorize('view', $payment); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'nextPaymentNumber' => $payment->getPaymentNumAttribute(), | ||||
|             'payment_prefix' => $payment->getPaymentPrefixAttribute(), | ||||
|             'payment' => $payment, | ||||
|         ]); | ||||
|         return new PaymentResource($payment); | ||||
|     } | ||||
| 
 | ||||
|     public function update(PaymentRequest $request, Payment $payment) | ||||
|     { | ||||
|         $this->authorize('update', $payment); | ||||
| 
 | ||||
|         $payment = $payment->updatePayment($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'payment' => $payment, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new PaymentResource($payment); | ||||
|     } | ||||
| 
 | ||||
|     public function delete(DeletePaymentsRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple payments'); | ||||
| 
 | ||||
|         Payment::deletePayments($request->ids); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Payment; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Payment; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\SendPaymentRequest; | ||||
| @ -16,6 +16,8 @@ class SendPaymentController extends Controller | ||||
|      */ | ||||
|     public function __invoke(SendPaymentRequest $request, Payment $payment) | ||||
|     { | ||||
|         $this->authorize('send payment', $payment); | ||||
| 
 | ||||
|         $response = $payment->send($request->all()); | ||||
| 
 | ||||
|         return response()->json($response); | ||||
| @ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Payment; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Payment; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Mail\Markdown; | ||||
|  | ||||
| class SendPaymentPreviewController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request, Payment $payment) | ||||
|     { | ||||
|         $this->authorize('send payment', $payment); | ||||
|  | ||||
|         $markdown = new Markdown(view(), config('mail.markdown')); | ||||
|  | ||||
|         return $markdown->render('emails.send.payment', ['data' => $payment->sendPaymentData($request->all())]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,94 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\RecurringInvoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\RecurringInvoiceRequest; | ||||
| use Crater\Http\Resources\RecurringInvoiceResource; | ||||
| use Crater\Models\RecurringInvoice; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class RecurringInvoiceController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', RecurringInvoice::class); | ||||
|  | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
|  | ||||
|         $recurringInvoices = RecurringInvoice::whereCompany() | ||||
|             ->applyFilters($request->all()) | ||||
|             ->paginateData($limit); | ||||
|  | ||||
|         return (RecurringInvoiceResource::collection($recurringInvoices)) | ||||
|             ->additional(['meta' => [ | ||||
|                 'recurring_invoice_total_count' => RecurringInvoice::whereCompany()->count(), | ||||
|             ]]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(RecurringInvoiceRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', RecurringInvoice::class); | ||||
|  | ||||
|         $recurringInvoice = RecurringInvoice::createFromRequest($request); | ||||
|  | ||||
|         return new RecurringInvoiceResource($recurringInvoice); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Crater\Models\RecurringInvoice  $recurringInvoice | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(RecurringInvoice $recurringInvoice) | ||||
|     { | ||||
|         $this->authorize('view', $recurringInvoice); | ||||
|  | ||||
|         return new RecurringInvoiceResource($recurringInvoice); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Crater\Models\RecurringInvoice  $recurringInvoice | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(RecurringInvoiceRequest $request, RecurringInvoice $recurringInvoice) | ||||
|     { | ||||
|         $this->authorize('update', $recurringInvoice); | ||||
|  | ||||
|         $recurringInvoice->updateFromRequest($request); | ||||
|  | ||||
|         return new RecurringInvoiceResource($recurringInvoice); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Crater\Models\RecurringInvoice  $recurringInvoice | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function delete(Request $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple recurring invoices'); | ||||
|  | ||||
|         RecurringInvoice::deleteRecurringInvoice($request->ids); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\RecurringInvoice; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\RecurringInvoice; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class RecurringInvoiceFrequencyController extends Controller | ||||
| { | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $nextInvoiceAt = RecurringInvoice::getNextInvoiceDate($request->frequency, $request->starts_at); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|             'next_invoice_at' => $nextInvoiceAt, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,12 +1,12 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Report; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\User; | ||||
| use Crater\Models\Customer; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\App; | ||||
| use PDF; | ||||
| @ -24,6 +24,8 @@ class CustomerSalesReportController extends Controller | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
| 
 | ||||
|         $this->authorize('view report', $company); | ||||
| 
 | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
| 
 | ||||
|         App::setLocale($locale); | ||||
| @ -31,14 +33,13 @@ class CustomerSalesReportController extends Controller | ||||
|         $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) { | ||||
|         $customers = Customer::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) | ||||
|             ->where('company_id', $company->id) | ||||
|             ->applyInvoiceFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->get(); | ||||
| 
 | ||||
| @ -83,6 +84,10 @@ class CustomerSalesReportController extends Controller | ||||
| 
 | ||||
|         $pdf = PDF::loadView('app.pdf.reports.sales-customers'); | ||||
| 
 | ||||
|         if ($request->has('preview')) { | ||||
|             return view('app.pdf.reports.sales-customers'); | ||||
|         } | ||||
| 
 | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Report; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| @ -24,16 +24,17 @@ class ExpensesReportController extends Controller | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
| 
 | ||||
|         $this->authorize('view report', $company); | ||||
| 
 | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
| 
 | ||||
|         App::setLocale($locale); | ||||
| 
 | ||||
|         $expenseCategories = Expense::with('category') | ||||
|         ->whereCompany($company->id) | ||||
|             ->whereCompanyId($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
| 
 | ||||
|         $totalAmount = 0; | ||||
|         foreach ($expenseCategories as $category) { | ||||
|             $totalAmount += $category->total_amount; | ||||
| @ -68,6 +69,10 @@ class ExpensesReportController extends Controller | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.expenses'); | ||||
| 
 | ||||
|         if ($request->has('preview')) { | ||||
|             return view('app.pdf.reports.expenses'); | ||||
|         } | ||||
| 
 | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Report; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| @ -24,6 +24,8 @@ class ItemSalesReportController extends Controller | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
| 
 | ||||
|         $this->authorize('view report', $company); | ||||
| 
 | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
| 
 | ||||
|         App::setLocale($locale); | ||||
| @ -67,6 +69,10 @@ class ItemSalesReportController extends Controller | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.sales-items'); | ||||
| 
 | ||||
|         if ($request->has('preview')) { | ||||
|             return view('app.pdf.reports.sales-items'); | ||||
|         } | ||||
| 
 | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Report; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| @ -25,17 +25,19 @@ class ProfitLossReportController extends Controller | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
| 
 | ||||
|         $this->authorize('view report', $company); | ||||
| 
 | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
| 
 | ||||
|         App::setLocale($locale); | ||||
| 
 | ||||
|         $invoicesAmount = Invoice::whereCompany($company->id) | ||||
|         $invoicesAmount = Invoice::whereCompanyId($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->wherePaidStatus(Invoice::STATUS_PAID) | ||||
|             ->sum('total'); | ||||
| 
 | ||||
|         $expenseCategories = Expense::with('category') | ||||
|         ->whereCompany($company->id) | ||||
|             ->whereCompanyId($company->id) | ||||
|             ->applyFilters($request->only(['from_date', 'to_date'])) | ||||
|             ->expensesAttributes() | ||||
|             ->get(); | ||||
| @ -76,6 +78,10 @@ class ProfitLossReportController extends Controller | ||||
|         ]); | ||||
|         $pdf = PDF::loadView('app.pdf.reports.profit-loss'); | ||||
| 
 | ||||
|         if ($request->has('preview')) { | ||||
|             return view('app.pdf.reports.profit-loss'); | ||||
|         } | ||||
| 
 | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Report; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Report; | ||||
| 
 | ||||
| use Carbon\Carbon; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| @ -24,6 +24,8 @@ class TaxSummaryReportController extends Controller | ||||
|     { | ||||
|         $company = Company::where('unique_hash', $hash)->first(); | ||||
| 
 | ||||
|         $this->authorize('view report', $company); | ||||
| 
 | ||||
|         $locale = CompanySetting::getSetting('language',  $company->id); | ||||
| 
 | ||||
|         App::setLocale($locale); | ||||
| @ -70,6 +72,10 @@ class TaxSummaryReportController extends Controller | ||||
| 
 | ||||
|         $pdf = PDF::loadView('app.pdf.reports.tax-summary'); | ||||
| 
 | ||||
|         if ($request->has('preview')) { | ||||
|             return view('app.pdf.reports.tax-summary'); | ||||
|         } | ||||
| 
 | ||||
|         if ($request->has('download')) { | ||||
|             return $pdf->download(); | ||||
|         } | ||||
							
								
								
									
										20
									
								
								app/Http/Controllers/V1/Admin/Role/AbilitiesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								app/Http/Controllers/V1/Admin/Role/AbilitiesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Role; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class AbilitiesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         return response()->json(['abilities' => config('abilities.abilities')]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										119
									
								
								app/Http/Controllers/V1/Admin/Role/RolesController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								app/Http/Controllers/V1/Admin/Role/RolesController.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Role; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\RoleRequest; | ||||
| use Crater\Http\Resources\RoleResource; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Silber\Bouncer\BouncerFacade; | ||||
| use Silber\Bouncer\Database\Role; | ||||
|  | ||||
| class RolesController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', Role::class); | ||||
|  | ||||
|         $roles = Role::when($request->has('orderByField'), function ($query) use ($request) { | ||||
|             return $query->orderBy($request['orderByField'], $request['orderBy']); | ||||
|         }) | ||||
|             ->when($request->company_id, function ($query) use ($request) { | ||||
|                 return $query->where('scope', $request->company_id); | ||||
|             }) | ||||
|             ->get(); | ||||
|  | ||||
|         return RoleResource::collection($roles); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function store(RoleRequest $request) | ||||
|     { | ||||
|         $this->authorize('create', Role::class); | ||||
|  | ||||
|         $role = Role::create($request->getRolePayload()); | ||||
|  | ||||
|         $this->syncAbilities($request, $role); | ||||
|  | ||||
|         return new RoleResource($role); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param  \Spatie\Permission\Models\Role $role | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function show(Role $role) | ||||
|     { | ||||
|         $this->authorize('view', $role); | ||||
|  | ||||
|         return new RoleResource($role); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @param  \Spatie\Permission\Models\Role $role | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function update(RoleRequest $request, Role $role) | ||||
|     { | ||||
|         $this->authorize('update', $role); | ||||
|  | ||||
|         $role->update($request->getRolePayload()); | ||||
|  | ||||
|         $this->syncAbilities($request, $role); | ||||
|  | ||||
|         return new RoleResource($role); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \Spatie\Permission\Models\Role $role | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function destroy(Role $role) | ||||
|     { | ||||
|         $this->authorize('delete', $role); | ||||
|  | ||||
|         $users = User::whereIs($role->name)->get()->toArray(); | ||||
|  | ||||
|         if (! empty($users)) { | ||||
|             return respondJson('role_attached_to_users', 'Roles Attached to user'); | ||||
|         } | ||||
|  | ||||
|         $role->delete(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true | ||||
|         ]); | ||||
|     } | ||||
|  | ||||
|     private function syncAbilities(RoleRequest $request, $role) | ||||
|     { | ||||
|         foreach (config('abilities.abilities') as $ability) { | ||||
|             $check = array_search($ability['ability'], array_column($request->abilities, 'ability')); | ||||
|             if ($check !== false) { | ||||
|                 BouncerFacade::allow($role)->to($ability['ability'], $ability['model']); | ||||
|             } else { | ||||
|                 BouncerFacade::disallow($role)->to($ability['ability'], $ability['model']); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
| @ -1,13 +1,14 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\CompanyRequest; | ||||
| use Crater\Http\Requests\ProfileRequest; | ||||
| use Crater\Http\Resources\CompanyResource; | ||||
| use Crater\Http\Resources\UserResource; | ||||
| use Crater\Models\Company; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| 
 | ||||
| class CompanyController extends Controller | ||||
| { | ||||
| @ -15,21 +16,9 @@ class CompanyController extends Controller | ||||
|      * Retrive the Admin account. | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function getUser() | ||||
|     public function getUser(Request $request) | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
| 
 | ||||
|         $user->load([ | ||||
|             'addresses', | ||||
|             'addresses.country', | ||||
|             'company', | ||||
|             'company.address', | ||||
|             'company.address.country', | ||||
|         ]); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|         ]); | ||||
|         return new UserResource($request->user()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -41,14 +30,11 @@ class CompanyController extends Controller | ||||
|      */ | ||||
|     public function updateProfile(ProfileRequest $request) | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
|         $user = $request->user(); | ||||
| 
 | ||||
|         $user->update($request->validated()); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new UserResource($user); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -58,16 +44,15 @@ class CompanyController extends Controller | ||||
|      */ | ||||
|     public function updateCompany(CompanyRequest $request) | ||||
|     { | ||||
|         $company = Auth::user()->company; | ||||
|         $company = Company::find($request->header('company')); | ||||
| 
 | ||||
|         $this->authorize('manage company', $company); | ||||
| 
 | ||||
|         $company->update($request->only('name')); | ||||
| 
 | ||||
|         $company->address()->updateOrCreate(['company_id' => $company->id], $request->except(['name'])); | ||||
|         $company->address()->updateOrCreate(['company_id' => $company->id], $request->address); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'company' => $company, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new CompanyResource($company); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -78,6 +63,10 @@ class CompanyController extends Controller | ||||
|      */ | ||||
|     public function uploadCompanyLogo(Request $request) | ||||
|     { | ||||
|         $company = Company::find($request->header('company')); | ||||
| 
 | ||||
|         $this->authorize('manage company', $company); | ||||
| 
 | ||||
|         $data = json_decode($request->company_logo); | ||||
| 
 | ||||
|         if ($data) { | ||||
| @ -105,23 +94,24 @@ class CompanyController extends Controller | ||||
|      */ | ||||
|     public function uploadAvatar(Request $request) | ||||
|     { | ||||
|         $data = json_decode($request->admin_avatar); | ||||
| 
 | ||||
|         if ($data) { | ||||
|         $user = auth()->user(); | ||||
| 
 | ||||
|             if ($user) { | ||||
|         if ($user && $request->hasFile('admin_avatar')) { | ||||
|             $user->clearMediaCollection('admin_avatar'); | ||||
| 
 | ||||
|             $user->addMediaFromRequest('admin_avatar') | ||||
|                 ->toMediaCollection('admin_avatar'); | ||||
|         } | ||||
| 
 | ||||
|         if ($user && $request->has('avatar')) { | ||||
|             $data = json_decode($request->avatar); | ||||
|             $user->clearMediaCollection('admin_avatar'); | ||||
| 
 | ||||
|             $user->addMediaFromBase64($data->data) | ||||
|                 ->usingFileName($data->name) | ||||
|                 ->toMediaCollection('admin_avatar'); | ||||
|         } | ||||
|         } | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new UserResource($user); | ||||
|     } | ||||
| } | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DiskEnvironmentRequest; | ||||
| use Crater\Http\Resources\FileDiskResource; | ||||
| use Crater\Models\FileDisk; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| @ -16,14 +17,14 @@ class DiskController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage file disk'); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
|         $disks = FileDisk::applyFilters($request->all()) | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'disks' => $disks, | ||||
|         ]); | ||||
|         return FileDiskResource::collection($disks); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -33,19 +34,15 @@ class DiskController extends Controller | ||||
|      */ | ||||
|     public function store(DiskEnvironmentRequest $request) | ||||
|     { | ||||
|         $this->authorize('manage file disk'); | ||||
| 
 | ||||
|         if (! FileDisk::validateCredentials($request->credentials, $request->driver)) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'error' => 'invalid_credentials', | ||||
|             ]); | ||||
|             return respondJson('invalid_credentials', 'Invalid Credentials.'); | ||||
|         } | ||||
| 
 | ||||
|         $disk = FileDisk::createDisk($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|             'disk' => $disk, | ||||
|         ]); | ||||
|         return new FileDiskResource($disk); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -56,15 +53,14 @@ class DiskController extends Controller | ||||
|      */ | ||||
|     public function update(FileDisk $disk, Request $request) | ||||
|     { | ||||
|         $this->authorize('manage file disk'); | ||||
| 
 | ||||
|         $credentials = $request->credentials; | ||||
|         $driver = $request->driver; | ||||
| 
 | ||||
|         if ($credentials && $driver && $disk->type !== 'SYSTEM') { | ||||
|             if (! FileDisk::validateCredentials($credentials, $driver)) { | ||||
|                 return response()->json([ | ||||
|                     'success' => false, | ||||
|                     'error' => 'invalid_credentials', | ||||
|                 ]); | ||||
|                 return respondJson('invalid_credentials', 'Invalid Credentials.'); | ||||
|             } | ||||
| 
 | ||||
|             $disk->updateDisk($request); | ||||
| @ -72,10 +68,7 @@ class DiskController extends Controller | ||||
|             $disk->setAsDefaultDisk(); | ||||
|         } | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|             'disk' => $disk, | ||||
|         ]); | ||||
|         return new FileDiskResource($disk); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -84,6 +77,8 @@ class DiskController extends Controller | ||||
|      */ | ||||
|     public function show($disk) | ||||
|     { | ||||
|         $this->authorize('manage file disk'); | ||||
| 
 | ||||
|         $diskData = []; | ||||
|         switch ($disk) { | ||||
|             case 'local': | ||||
| @ -142,10 +137,10 @@ class DiskController extends Controller | ||||
|      */ | ||||
|     public function destroy(FileDisk $disk) | ||||
|     { | ||||
|         $this->authorize('manage file disk'); | ||||
| 
 | ||||
|         if ($disk->setAsDefault() && $disk->type === 'SYSTEM') { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|             ]); | ||||
|             return respondJson('not_allowed', 'Not Allowed'); | ||||
|         } | ||||
| 
 | ||||
|         $disk->delete(); | ||||
| @ -161,6 +156,8 @@ class DiskController extends Controller | ||||
|      */ | ||||
|     public function getDiskDrivers() | ||||
|     { | ||||
|         $this->authorize('manage file disk'); | ||||
| 
 | ||||
|         $drivers = [ | ||||
|             [ | ||||
|                 'name' => 'Local', | ||||
| @ -0,0 +1,25 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class GetCompanyMailConfigurationController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $mailConfig = [ | ||||
|             'from_name' => config('mail.from.name'), | ||||
|             'from_mail' => config('mail.from.address'), | ||||
|         ]; | ||||
|  | ||||
|         return response()->json($mailConfig); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\GetSettingsRequest; | ||||
| @ -1,8 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Auth; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\GetSettingsRequest; | ||||
| 
 | ||||
| @ -16,7 +15,7 @@ class GetUserSettingsController extends Controller | ||||
|      */ | ||||
|     public function __invoke(GetSettingsRequest $request) | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
|         $user = $request->user(); | ||||
| 
 | ||||
|         return response()->json($user->getSettings($request->settings)); | ||||
|     } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\MailEnvironmentRequest; | ||||
| @ -33,6 +33,8 @@ class MailConfigurationController extends Controller | ||||
|      */ | ||||
|     public function saveMailEnvironment(MailEnvironmentRequest $request) | ||||
|     { | ||||
|         $this->authorize('manage email config'); | ||||
| 
 | ||||
|         $setting = Setting::getSetting('profile_complete'); | ||||
|         $results = $this->environmentManager->saveMailVariables($request); | ||||
| 
 | ||||
| @ -45,6 +47,8 @@ class MailConfigurationController extends Controller | ||||
| 
 | ||||
|     public function getMailEnvironment() | ||||
|     { | ||||
|         $this->authorize('manage email config'); | ||||
| 
 | ||||
|         $MailData = [ | ||||
|             'mail_driver' => config('mail.driver'), | ||||
|             'mail_host' => config('mail.host'), | ||||
| @ -71,6 +75,8 @@ class MailConfigurationController extends Controller | ||||
|      */ | ||||
|     public function getMailDrivers() | ||||
|     { | ||||
|         $this->authorize('manage email config'); | ||||
| 
 | ||||
|         $drivers = [ | ||||
|             'smtp', | ||||
|             'mail', | ||||
| @ -84,6 +90,8 @@ class MailConfigurationController extends Controller | ||||
| 
 | ||||
|     public function testEmailConfig(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage email config'); | ||||
| 
 | ||||
|         $this->validate($request, [ | ||||
|             'to' => 'required|email', | ||||
|             'subject' => 'required', | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\TaxTypeRequest; | ||||
| use Crater\Http\Resources\TaxTypeResource; | ||||
| use Crater\Models\TaxType; | ||||
| use Illuminate\Http\Request; | ||||
| 
 | ||||
| @ -16,21 +17,16 @@ class TaxTypesController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', TaxType::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 5; | ||||
| 
 | ||||
|         $taxTypes = TaxType::whereCompany($request->header('company')) | ||||
|             ->applyFilters($request->only([ | ||||
|                 'tax_type_id', | ||||
|                 'search', | ||||
|                 'orderByField', | ||||
|                 'orderBy', | ||||
|             ])) | ||||
|         $taxTypes = TaxType::applyFilters($request->all()) | ||||
|             ->whereCompany() | ||||
|             ->latest() | ||||
|             ->paginateData($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'taxTypes' => $taxTypes, | ||||
|         ]); | ||||
|         return TaxTypeResource::collection($taxTypes); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -41,15 +37,11 @@ class TaxTypesController extends Controller | ||||
|      */ | ||||
|     public function store(TaxTypeRequest $request) | ||||
|     { | ||||
|         $data = $request->validated(); | ||||
|         $this->authorize('create', TaxType::class); | ||||
| 
 | ||||
|         $data['company_id'] = $request->header('company'); | ||||
|         $taxType = TaxType::create($request->getTaxTypePayload()); | ||||
| 
 | ||||
|         $taxType = TaxType::create($data); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'taxType' => $taxType, | ||||
|         ]); | ||||
|         return new TaxTypeResource($taxType); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -60,9 +52,9 @@ class TaxTypesController extends Controller | ||||
|      */ | ||||
|     public function show(TaxType $taxType) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'taxType' => $taxType, | ||||
|         ]); | ||||
|         $this->authorize('view', $taxType); | ||||
| 
 | ||||
|         return new TaxTypeResource($taxType); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -74,11 +66,11 @@ class TaxTypesController extends Controller | ||||
|      */ | ||||
|     public function update(TaxTypeRequest $request, TaxType $taxType) | ||||
|     { | ||||
|         $taxType->update($request->validated()); | ||||
|         $this->authorize('update', $taxType); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'taxType' => $taxType, | ||||
|         ]); | ||||
|         $taxType->update($request->getTaxTypePayload()); | ||||
| 
 | ||||
|         return new TaxTypeResource($taxType); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -89,11 +81,12 @@ class TaxTypesController extends Controller | ||||
|      */ | ||||
|     public function destroy(TaxType $taxType) | ||||
|     { | ||||
|         $this->authorize('delete', $taxType); | ||||
| 
 | ||||
|         if ($taxType->taxes() && $taxType->taxes()->count() > 0) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|             ]); | ||||
|             return respondJson('taxes_attached', 'Taxes Attached.'); | ||||
|         } | ||||
| 
 | ||||
|         $taxType->delete(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -1,9 +1,10 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\UpdateSettingsRequest; | ||||
| use Crater\Models\Company; | ||||
| use Crater\Models\CompanySetting; | ||||
| 
 | ||||
| class UpdateCompanySettingsController extends Controller | ||||
| @ -16,6 +17,8 @@ class UpdateCompanySettingsController extends Controller | ||||
|      */ | ||||
|     public function __invoke(UpdateSettingsRequest $request) | ||||
|     { | ||||
|         $this->authorize('manage company', Company::find($request->header('company'))); | ||||
| 
 | ||||
|         CompanySetting::setSettings($request->settings, $request->header('company')); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -1,8 +1,7 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Settings; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Settings; | ||||
| 
 | ||||
| use Auth; | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\UpdateSettingsRequest; | ||||
| 
 | ||||
| @ -16,7 +15,7 @@ class UpdateUserSettingsController extends Controller | ||||
|      */ | ||||
|     public function __invoke(UpdateSettingsRequest $request) | ||||
|     { | ||||
|         $user = Auth::user(); | ||||
|         $user = $request->user(); | ||||
| 
 | ||||
|         $user->setSettings($request->settings); | ||||
| 
 | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Setting; | ||||
| @ -17,6 +17,13 @@ class CheckVersionController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
| 
 | ||||
|         set_time_limit(600); // 10 minutes
 | ||||
| 
 | ||||
|         $json = Updater::checkForUpdate(Setting::getSetting('version')); | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| @ -16,6 +16,13 @@ class CopyFilesController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'path' => 'required', | ||||
|         ]); | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| @ -16,6 +16,13 @@ class DeleteFilesController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
| 
 | ||||
|         if (isset($request->deleted_files) && ! empty($request->deleted_files)) { | ||||
|             Updater::deleteFiles($request->deleted_files); | ||||
|         } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| @ -16,6 +16,13 @@ class DownloadUpdateController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'version' => 'required', | ||||
|         ]); | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| @ -16,6 +16,13 @@ class FinishUpdateController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'installed' => 'required', | ||||
|             'version' => 'required', | ||||
| @ -0,0 +1,32 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
|  | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| class MigrateUpdateController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
|  | ||||
|         Updater::migrateUpdate(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'success' => true, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Space\Updater; | ||||
| @ -16,6 +16,13 @@ class UnzipUpdateController extends Controller | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         if ((! $request->user()) || (! $request->user()->isOwner())) { | ||||
|             return response()->json([ | ||||
|                 'success' => false, | ||||
|                 'message' => 'You are not allowed to update this app.' | ||||
|             ], 401); | ||||
|         } | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'path' => 'required', | ||||
|         ]); | ||||
| @ -1,6 +1,6 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Update; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Update; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Models\Setting; | ||||
| @ -11,6 +11,8 @@ class UpdateController extends Controller | ||||
| { | ||||
|     public function download(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage update app'); | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'version' => 'required', | ||||
|         ]); | ||||
| @ -25,6 +27,8 @@ class UpdateController extends Controller | ||||
| 
 | ||||
|     public function unzip(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage update app'); | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'path' => 'required', | ||||
|         ]); | ||||
| @ -46,6 +50,8 @@ class UpdateController extends Controller | ||||
| 
 | ||||
|     public function copyFiles(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage update app'); | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'path' => 'required', | ||||
|         ]); | ||||
| @ -60,6 +66,8 @@ class UpdateController extends Controller | ||||
| 
 | ||||
|     public function migrate(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage update app'); | ||||
| 
 | ||||
|         Updater::migrateUpdate(); | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -69,6 +77,8 @@ class UpdateController extends Controller | ||||
| 
 | ||||
|     public function finishUpdate(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage update app'); | ||||
| 
 | ||||
|         $request->validate([ | ||||
|             'installed' => 'required', | ||||
|             'version' => 'required', | ||||
| @ -81,6 +91,8 @@ class UpdateController extends Controller | ||||
| 
 | ||||
|     public function checkLatestVersion(Request $request) | ||||
|     { | ||||
|         $this->authorize('manage update app'); | ||||
| 
 | ||||
|         set_time_limit(600); // 10 minutes
 | ||||
| 
 | ||||
|         $json = Updater::checkForUpdate(Setting::getSetting('version')); | ||||
| @ -1,13 +1,13 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Users; | ||||
| namespace Crater\Http\Controllers\V1\Admin\Users; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Http\Requests\DeleteUserRequest; | ||||
| use Crater\Http\Requests\UserRequest; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Http\Resources\UserResource; | ||||
| use Crater\Models\User; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Facades\Auth; | ||||
| 
 | ||||
| class UsersController extends Controller | ||||
| { | ||||
| @ -19,24 +19,21 @@ class UsersController extends Controller | ||||
|      */ | ||||
|     public function index(Request $request) | ||||
|     { | ||||
|         $this->authorize('viewAny', User::class); | ||||
| 
 | ||||
|         $limit = $request->has('limit') ? $request->limit : 10; | ||||
| 
 | ||||
|         $users = User::where('role', 'admin', 'creator') | ||||
|             ->applyFilters( | ||||
|                 $request->only([ | ||||
|                     'phone', | ||||
|                     'email', | ||||
|                     'display_name', | ||||
|                     'orderByField', | ||||
|                     'orderBy', | ||||
|                 ]) | ||||
|             ) | ||||
|         $user = $request->user(); | ||||
| 
 | ||||
|         $users = User::applyFilters($request->all()) | ||||
|             ->where('id', '<>', $user->id) | ||||
|             ->latest() | ||||
|             ->paginate($limit); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'users' => $users, | ||||
|         ]); | ||||
|         return UserResource::collection($users) | ||||
|             ->additional(['meta' => [ | ||||
|                 'user_total_count' => User::count(), | ||||
|             ]]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -47,20 +44,11 @@ class UsersController extends Controller | ||||
|      */ | ||||
|     public function store(UserRequest $request) | ||||
|     { | ||||
|         $data = $request->validated(); | ||||
|         $data['role'] = 'admin'; | ||||
|         $data['company_id'] = Auth::user()->company_id; | ||||
|         $data['creator_id'] = Auth::id(); | ||||
|         $user = User::create($data); | ||||
|         $this->authorize('create', User::class); | ||||
| 
 | ||||
|         $user->setSettings([ | ||||
|             'language' => CompanySetting::getSetting('language', $user->company_id), | ||||
|         ]); | ||||
|         $user = User::createFromRequest($request); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         return new UserResource($user); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -71,10 +59,9 @@ class UsersController extends Controller | ||||
|      */ | ||||
|     public function show(User $user) | ||||
|     { | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         $this->authorize('view', $user); | ||||
| 
 | ||||
|         return new UserResource($user); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -86,12 +73,11 @@ class UsersController extends Controller | ||||
|      */ | ||||
|     public function update(UserRequest $request, User $user) | ||||
|     { | ||||
|         $user->update($request->validated()); | ||||
|         $this->authorize('update', $user); | ||||
| 
 | ||||
|         return response()->json([ | ||||
|             'user' => $user, | ||||
|             'success' => true, | ||||
|         ]); | ||||
|         $user->updateFromRequest($request); | ||||
| 
 | ||||
|         return new UserResource($user); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -100,10 +86,12 @@ class UsersController extends Controller | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function delete(Request $request) | ||||
|     public function delete(DeleteUserRequest $request) | ||||
|     { | ||||
|         $this->authorize('delete multiple users', User::class); | ||||
| 
 | ||||
|         if ($request->users) { | ||||
|             User::destroy($request->users); | ||||
|             User::deleteUsers($request->users); | ||||
|         } | ||||
| 
 | ||||
|         return response()->json([ | ||||
| @ -1,120 +0,0 @@ | ||||
| <?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, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,12 +1,12 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Mobile\Customer; | ||||
| namespace Crater\Http\Controllers\V1\Customer; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Mail\EstimateViewedMail; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Customer; | ||||
| use Crater\Models\Estimate; | ||||
| use Crater\Models\User; | ||||
| 
 | ||||
| class EstimatePdfController extends Controller | ||||
| { | ||||
| @ -28,7 +28,7 @@ class EstimatePdfController extends Controller | ||||
| 
 | ||||
|             if ($notifyEstimateViewed == 'YES') { | ||||
|                 $data['estimate'] = Estimate::findOrFail($estimate->id)->toArray(); | ||||
|                 $data['user'] = User::find($estimate->user_id)->toArray(); | ||||
|                 $data['user'] = Customer::find($estimate->customer_id)->toArray(); | ||||
|                 $notificationEmail = CompanySetting::getSetting( | ||||
|                     'notification_email', | ||||
|                     $estimate->company_id | ||||
| @ -1,12 +1,12 @@ | ||||
| <?php | ||||
| 
 | ||||
| namespace Crater\Http\Controllers\V1\Mobile\Customer; | ||||
| namespace Crater\Http\Controllers\V1\Customer; | ||||
| 
 | ||||
| use Crater\Http\Controllers\Controller; | ||||
| use Crater\Mail\InvoiceViewedMail; | ||||
| use Crater\Models\CompanySetting; | ||||
| use Crater\Models\Customer; | ||||
| use Crater\Models\Invoice; | ||||
| use Crater\Models\User; | ||||
| 
 | ||||
| class InvoicePdfController extends Controller | ||||
| { | ||||
| @ -29,7 +29,7 @@ class InvoicePdfController extends Controller | ||||
| 
 | ||||
|             if ($notifyInvoiceViewed == 'YES') { | ||||
|                 $data['invoice'] = Invoice::findOrFail($invoice->id)->toArray(); | ||||
|                 $data['user'] = User::find($invoice->user_id)->toArray(); | ||||
|                 $data['user'] = Customer::find($invoice->customer_id)->toArray(); | ||||
|                 $notificationEmail = CompanySetting::getSetting( | ||||
|                     'notification_email', | ||||
|                     $invoice->company_id | ||||
| @ -1,32 +0,0 @@ | ||||
| <?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,145 +0,0 @@ | ||||
| <?php | ||||
|  | ||||
| namespace Crater\Http\Controllers\V1\Dashboard; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| 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 | ||||
| { | ||||
|     /** | ||||
|      * Handle the incoming request. | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request  $request | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function __invoke(Request $request) | ||||
|     { | ||||
|         $invoiceTotals = []; | ||||
|         $expenseTotals = []; | ||||
|         $receiptTotals = []; | ||||
|         $netProfits = []; | ||||
|         $i = 0; | ||||
|         $months = []; | ||||
|         $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')) | ||||
|                 ->sum('total') | ||||
|             ); | ||||
|             array_push( | ||||
|                 $expenseTotals, | ||||
|                 Expense::whereBetween( | ||||
|                     'expense_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                 ->whereCompany($request->header('company')) | ||||
|                 ->sum('amount') | ||||
|             ); | ||||
|             array_push( | ||||
|                 $receiptTotals, | ||||
|                 Payment::whereBetween( | ||||
|                     'payment_date', | ||||
|                     [$start->format('Y-m-d'), $end->format('Y-m-d')] | ||||
|                 ) | ||||
|                 ->whereCompany($request->header('company')) | ||||
|                 ->sum('amount') | ||||
|             ); | ||||
|             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')] | ||||
|             ) | ||||
|             ->sum('total'); | ||||
|         $totalReceipts = Payment::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|                 'payment_date', | ||||
|                 [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|             ) | ||||
|             ->sum('amount'); | ||||
|         $totalExpenses = Expense::whereCompany($request->header('company')) | ||||
|             ->whereBetween( | ||||
|                 'expense_date', | ||||
|                 [$startDate->format('Y-m-d'), $start->format('Y-m-d')] | ||||
|             ) | ||||
|             ->sum('amount'); | ||||
|         $netProfit = (int)$totalReceipts - (int)$totalExpenses; | ||||
|  | ||||
|         $chartData = [ | ||||
|             'months' => $months, | ||||
|             'invoiceTotals' => $invoiceTotals, | ||||
|             'expenseTotals' => $expenseTotals, | ||||
|             'receiptTotals' => $receiptTotals, | ||||
|             'netProfits' => $netProfits, | ||||
|         ]; | ||||
|  | ||||
|         $customersCount = User::customer()->whereCompany($request->header('company'))->get()->count(); | ||||
|         $invoicesCount = Invoice::whereCompany($request->header('company'))->get()->count(); | ||||
|         $estimatesCount = Estimate::whereCompany($request->header('company'))->get()->count(); | ||||
|         $totalDueAmount = Invoice::whereCompany($request->header('company'))->sum('due_amount'); | ||||
|         $dueInvoices = Invoice::with('user')->whereCompany($request->header('company'))->where('due_amount', '>', 0)->take(5)->latest()->get(); | ||||
|         $estimates = Estimate::with('user')->whereCompany($request->header('company'))->take(5)->latest()->get(); | ||||
|  | ||||
|         return response()->json([ | ||||
|             'dueInvoices' => $dueInvoices, | ||||
|             'estimates' => $estimates, | ||||
|             'estimatesCount' => $estimatesCount, | ||||
|             'totalDueAmount' => $totalDueAmount, | ||||
|             'invoicesCount' => $invoicesCount, | ||||
|             'customersCount' => $customersCount, | ||||
|             'chartData' => $chartData, | ||||
|             'salesTotal' => $salesTotal, | ||||
|             'totalReceipts' => $totalReceipts, | ||||
|             'totalExpenses' => $totalExpenses, | ||||
|             'netProfit' => $netProfit, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,95 +0,0 @@ | ||||
| <?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, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,104 +0,0 @@ | ||||
| <?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, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
| @ -1,40 +0,0 @@ | ||||
| <?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, | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	