├── storage ├── logs │ └── .gitignore ├── app │ ├── public │ │ └── .gitignore │ └── .gitignore └── framework │ ├── testing │ └── .gitignore │ ├── views │ └── .gitignore │ ├── cache │ ├── data │ │ └── .gitignore │ └── .gitignore │ ├── sessions │ └── .gitignore │ └── .gitignore ├── database ├── .gitignore ├── seeders │ ├── FakerDealsSeeder.php │ ├── FakerProductsSeeder.php │ ├── FakerSalesSeeder.php │ ├── FakerTasksSeeder.php │ ├── FakerEmployeesSeeder.php │ ├── FakerClientSeeder.php │ ├── FakerFinancesSeeder.php │ ├── FakerCompaniesSeeder.php │ ├── AdminAccSeeder.php │ ├── DatabaseSeeder.php │ └── SettingsSeeder.php ├── migrations │ ├── 2024_09_27_131146_drop_reports_table.php │ ├── 2024_10_15_095913_add_is_visible_to_settings_table.php │ ├── 2024_09_27_122828_rename_companies_id_to_company_id_in_deals_table.php │ ├── 2024_09_27_123343_rename_companies_id_to_company_id_in_finances_table.php │ ├── 2024_11_26_104225_rename_tables.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2024_10_17_083819_change_start_time_and_end_time_in_deals_table.php │ ├── 2024_09_12_175506_create_sessions_table.php │ ├── 2020_01_19_131843_add_settings_table.php │ ├── 2020_01_22_121759_add_deals_terms_table.php │ ├── 2014_10_12_000000_create_admins_table.php │ ├── 2024_09_12_174147_create_cache_table.php │ ├── 2017_08_18_073557_create_table_deals.php │ ├── 2017_09_13_171236_create_table_products.php │ ├── 2017_11_18_122319_SystemLogs.php │ ├── 2017_08_08_063939_create_table_clients.php │ ├── 2017_09_12_124214_create_table_tasks.php │ ├── 2017_09_13_171248_create_table_sales.php │ ├── 2017_09_13_171158_create_table_reports.php │ ├── 2017_08_19_101613_create_table_Employees.php │ ├── 2017_08_08_063944_create_table_companies.php │ └── 2017_09_13_171227_create_table_finances.php └── factories │ ├── DealTermFactory.php │ ├── ProductFactory.php │ ├── AdministratorFactory.php │ ├── DealFactory.php │ ├── TaskFactory.php │ ├── SaleFactory.php │ ├── EmployeeFactory.php │ ├── ClientFactory.php │ ├── FinanceFactory.php │ └── CompanyFactory.php ├── public ├── robots.txt ├── images │ ├── avatar.png │ ├── loader.gif │ └── favicon.ico ├── index.php └── .htaccess ├── resources ├── views │ ├── crm │ │ ├── deals │ │ │ └── terms │ │ │ │ ├── terms_pdf.blade.php │ │ │ │ └── create.blade.php │ │ ├── dashboard │ │ │ └── components │ │ │ │ └── charts.blade.php │ │ ├── auth │ │ │ ├── login.blade.php │ │ │ └── passwords │ │ │ │ └── reset.blade.php │ │ ├── products │ │ │ └── create.blade.php │ │ └── sales │ │ │ └── show.blade.php │ └── layouts │ │ ├── footer.blade.php │ │ ├── components │ │ ├── forms │ │ │ ├── input.blade.php │ │ │ ├── textarea.blade.php │ │ │ └── select.blade.php │ │ └── stats.blade.php │ │ ├── header.blade.php │ │ ├── head.blade.php │ │ └── flash-messages.blade.php └── lang │ └── en │ ├── pagination.php │ ├── auth.php │ ├── passwords.php │ └── messages.php ├── bootstrap ├── providers.php ├── app.php └── cache │ └── packages.php ├── app ├── Enums │ ├── Settings.php │ └── RoleType.php ├── Services │ ├── AdminService.php │ ├── SalesService.php │ ├── ProductsService.php │ ├── SettingsService.php │ ├── SystemLogService.php │ ├── CompaniesService.php │ ├── FinancesService.php │ ├── ClientService.php │ ├── EmployeesService.php │ ├── DealsService.php │ ├── TasksService.php │ ├── GraphDataService.php │ └── CalculateCashService.php ├── Models │ ├── Setting.php │ ├── DealTerm.php │ ├── Product.php │ ├── Task.php │ ├── Deal.php │ ├── Sale.php │ ├── Client.php │ ├── Finance.php │ ├── SystemLog.php │ ├── Employee.php │ ├── Company.php │ └── Administrator.php ├── Relations │ ├── Belongs │ │ ├── BelongsToDeal.php │ │ ├── BelongsToClient.php │ │ ├── BelongsToCompany.php │ │ ├── BelongsToEmployee.php │ │ └── BelongsToProduct.php │ └── Has │ │ ├── HasManySales.php │ │ ├── HasManyTasks.php │ │ ├── HasManyCompanies.php │ │ ├── HasManyDeals.php │ │ ├── HasManyDealTerms.php │ │ ├── HasManyEmployees.php │ │ └── HasManyFinances.php ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ └── CRM │ │ │ ├── SettingsController.php │ │ │ └── AuthController.php │ └── Requests │ │ ├── StoreDealTermRequest.php │ │ ├── LoginAdminRequest.php │ │ ├── TaskStoreRequest.php │ │ ├── ChangePasswordRequest.php │ │ ├── DealStoreRequest.php │ │ ├── TaskUpdateRequest.php │ │ ├── ProductStoreRequest.php │ │ ├── DealUpdateRequest.php │ │ ├── SaleStoreRequest.php │ │ ├── ProductUpdateRequest.php │ │ ├── SettingsStoreRequest.php │ │ ├── SaleUpdateRequest.php │ │ ├── EmployeeStoreRequest.php │ │ ├── FinanceStoreRequest.php │ │ ├── EmployeeUpdateRequest.php │ │ ├── FinanceUpdateRequest.php │ │ ├── ClientStoreRequest.php │ │ ├── ClientUpdateRequest.php │ │ ├── CompanyStoreRequest.php │ │ └── CompanyUpdateRequest.php ├── Providers │ ├── BroadcastServiceProvider.php │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── EventServiceProvider.php │ └── RouteServiceProvider.php ├── Queries │ ├── SettingQueries.php │ ├── FinanceQueries.php │ ├── SystemLogQueries.php │ ├── SaleQueries.php │ ├── DealQueries.php │ ├── EmployeeQueries.php │ ├── ProductQueries.php │ ├── ClientQueries.php │ ├── CompanyQueries.php │ └── TaskQueries.php ├── Traits │ └── Language.php ├── Jobs │ ├── Deal │ │ ├── UpdateDealJob.php │ │ ├── StoreDealTermJob.php │ │ └── StoreDealJob.php │ ├── Sale │ │ ├── UpdateSaleJob.php │ │ └── StoreSaleJob.php │ ├── Task │ │ ├── UpdateTaskJob.php │ │ └── StoreTaskJob.php │ ├── Client │ │ ├── UpdateClientJob.php │ │ └── StoreClientJob.php │ ├── Product │ │ ├── UpdateProductJob.php │ │ └── StoreProductJob.php │ ├── Employee │ │ ├── UpdateEmployeeJob.php │ │ └── StoreEmployeeJob.php │ ├── Company │ │ ├── UpdateCompanyJob.php │ │ └── StoreCompanyJob.php │ ├── UpdateSettingsJob.php │ ├── ChangePasswordJob.php │ ├── Finance │ │ ├── UpdateFinanceJob.php │ │ └── StoreFinanceJob.php │ └── StoreSystemLogJob.php └── Console │ ├── Kernel.php │ └── Commands │ └── processSoftCRM.php ├── tests ├── TestCase.php ├── Unit │ └── ExampleTest.php └── Feature │ └── ExampleTest.php ├── .gitattributes ├── routes └── console.php ├── package.json ├── .editorconfig ├── .gitignore ├── artisan ├── MIT_License.txt ├── config ├── services.php ├── filesystems.php ├── cache.php └── mail.php ├── phpunit.xml ├── .env.example ├── composer.json └── CODE_OF_CONDUCT.md /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | *.sqlite-journal 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /resources/views/crm/deals/terms/terms_pdf.blade.php: -------------------------------------------------------------------------------- 1 | {!! $body !!} -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /public/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamgrzeski/SoftCRM/HEAD/public/images/avatar.png -------------------------------------------------------------------------------- /public/images/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kamgrzeski/SoftCRM/HEAD/public/images/loader.gif -------------------------------------------------------------------------------- /bootstrap/providers.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 8 | })->purpose('Display an inspiring quote')->hourly(); 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "type": "module", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vite build" 7 | }, 8 | "devDependencies": { 9 | "axios": "^1.7.4", 10 | "laravel-vite-plugin": "^1.0", 11 | "vite": "^5.0" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/Relations/Belongs/BelongsToDeal.php: -------------------------------------------------------------------------------- 1 | belongsTo(Deal::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Relations/Belongs/BelongsToClient.php: -------------------------------------------------------------------------------- 1 | belongsTo(Client::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Relations/Has/HasManySales.php: -------------------------------------------------------------------------------- 1 | hasMany(Sale::class, 'product_id'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Relations/Has/HasManyTasks.php: -------------------------------------------------------------------------------- 1 | hasMany(Task::class, 'employee_id'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/Unit/ExampleTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/Relations/Belongs/BelongsToCompany.php: -------------------------------------------------------------------------------- 1 | belongsTo(Company::class); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/Relations/Belongs/BelongsToEmployee.php: -------------------------------------------------------------------------------- 1 | belongsTo(Employee::class); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_size = 4 7 | indent_style = space 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | 17 | [docker-compose.yml] 18 | indent_size = 4 19 | -------------------------------------------------------------------------------- /app/Relations/Has/HasManyCompanies.php: -------------------------------------------------------------------------------- 1 | hasMany(Company::class, 'client_id'); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/Relations/Belongs/BelongsToProduct.php: -------------------------------------------------------------------------------- 1 | belongsTo(Product::class, 'product_id'); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.phpunit.cache 2 | /node_modules 3 | /public/build 4 | /public/hot 5 | /public/storage 6 | /storage/*.key 7 | /vendor 8 | .env 9 | .env.backup 10 | .env.production 11 | .phpactor.json 12 | .phpunit.result.cache 13 | Homestead.json 14 | Homestead.yaml 15 | auth.json 16 | npm-debug.log 17 | yarn-error.log 18 | /.fleet 19 | /.idea 20 | /.vscode 21 | /.zed 22 | -------------------------------------------------------------------------------- /app/Models/DealTerm.php: -------------------------------------------------------------------------------- 1 | hasMany(Deal::class, 'id'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/Relations/Has/HasManyDealTerms.php: -------------------------------------------------------------------------------- 1 | hasMany(DealTerm::class, 'deal_id'); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /database/seeders/FakerDealsSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /database/seeders/FakerProductsSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /database/seeders/FakerSalesSeeder.php: -------------------------------------------------------------------------------- 1 | count(10)->create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /database/seeders/FakerTasksSeeder.php: -------------------------------------------------------------------------------- 1 | count(10)->create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | handleCommand(new ArgvInput); 14 | 15 | exit($status); 16 | -------------------------------------------------------------------------------- /database/seeders/FakerEmployeesSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /resources/views/crm/dashboard/components/charts.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {!! $tasksGraphData->render() !!} 5 |
6 |
7 | {!! $itemsCountGraphData->render() !!} 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /app/Relations/Has/HasManyEmployees.php: -------------------------------------------------------------------------------- 1 | hasMany(Employee::class, 'client_id'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /database/seeders/FakerClientSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Relations/Has/HasManyFinances.php: -------------------------------------------------------------------------------- 1 | hasMany(Finance::class); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /database/seeders/FakerFinancesSeeder.php: -------------------------------------------------------------------------------- 1 | count(10)->create(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/Product.php: -------------------------------------------------------------------------------- 1 | get('/'); 16 | 17 | $response->assertStatus(200); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/Models/Task.php: -------------------------------------------------------------------------------- 1 | handleRequest(Request::capture()); 18 | -------------------------------------------------------------------------------- /app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'datetime' 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /app/Models/Client.php: -------------------------------------------------------------------------------- 1 | withRouting( 9 | web: __DIR__.'/../routes/web.php', 10 | commands: __DIR__.'/../routes/console.php', 11 | health: '/up', 12 | ) 13 | ->withMiddleware(function (Middleware $middleware) { 14 | // 15 | }) 16 | ->withExceptions(function (Exceptions $exceptions) { 17 | // 18 | })->create(); 19 | -------------------------------------------------------------------------------- /database/migrations/2024_09_27_131146_drop_reports_table.php: -------------------------------------------------------------------------------- 1 | 'datetime', 19 | ]; 20 | } 21 | -------------------------------------------------------------------------------- /app/Models/SystemLog.php: -------------------------------------------------------------------------------- 1 | getHttpHost(); 21 | 22 | if (strpos($hostName, 'localhost') != 0) { 23 | $this->ip = request()->ip(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /database/seeders/FakerCompaniesSeeder.php: -------------------------------------------------------------------------------- 1 | pluck('id')->toArray(); 18 | 19 | Company::factory(10)->create([ 20 | 'client_id' => function() use ($userIds) { 21 | return $userIds[array_rand($userIds)]; 22 | } 23 | ]); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/factories/DealTermFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class DealTermFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'body' => $this->faker->text, 22 | 'deal_id' => Deal::get()->random()->id, 23 | ]; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /database/seeders/AdminAccSeeder.php: -------------------------------------------------------------------------------- 1 | create([ 20 | 'name' => 'admin', 21 | 'email' => 'admin@admin.com', 22 | 'password' => Hash::make('admin'), 23 | 'role_type' => RoleType::ADMIN_TYPE 24 | ]); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Http/Requests/StoreDealTermRequest.php: -------------------------------------------------------------------------------- 1 | ['required'] 28 | 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Queries/SettingQueries.php: -------------------------------------------------------------------------------- 1 | get()->last()->value; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Services/CompaniesService.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /app/Http/Requests/LoginAdminRequest.php: -------------------------------------------------------------------------------- 1 | ['required'], 28 | 'password' => ['required'] 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Models/Employee.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/views/layouts/footer.blade.php: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /app/Models/Company.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string', 28 | 'employee_id' => 'required', 29 | 'duration' => 'required|integer' 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Traits/Language.php: -------------------------------------------------------------------------------- 1 | ['required'], 28 | 'new_password' => ['required'], 29 | 'confirm_password' => ['required', 'same:new_password'] 30 | ]; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2024_10_15_095913_add_is_visible_to_settings_table.php: -------------------------------------------------------------------------------- 1 | boolean('is_visible')->default(true)->after('description'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('settings', function (Blueprint $table) { 25 | $table->dropColumn('is_visible'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /app/Http/Requests/DealStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string', 28 | 'start_time' => 'required', 29 | 'end_time' => 'required', 30 | 'company_id' => 'required|integer', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/factories/ProductFactory.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class ProductFactory extends Factory 11 | { 12 | /** 13 | * Define the model's default state. 14 | * 15 | * @return array 16 | */ 17 | public function definition(): array 18 | { 19 | return [ 20 | 'name' => $this->faker->name, 21 | 'category' => $this->faker->name, 22 | 'count' => $this->faker->randomNumber(3), 23 | 'price' => $this->faker->randomNumber(3), 24 | 'is_active' => $this->faker->boolean, 25 | 'admin_id' => 1, 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/Http/Requests/TaskUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'name' => 'required|string', 29 | 'employee_id' => 'required|integer', 30 | 'duration' => 'required|integer' 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/factories/AdministratorFactory.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class AdministratorFactory extends Factory 13 | { 14 | /** 15 | * Define the model's default state. 16 | * 17 | * @return array 18 | */ 19 | public function definition(): array 20 | { 21 | return [ 22 | 'name' => $this->faker->name, 23 | 'email' => $this->faker->unique()->safeEmail, 24 | 'password' => Hash::make('password'), 25 | 'role_type' => RoleType::USER_TYPE->value 26 | ]; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /database/migrations/2024_09_27_122828_rename_companies_id_to_company_id_in_deals_table.php: -------------------------------------------------------------------------------- 1 | renameColumn('companies_id', 'company_id'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('deals', function (Blueprint $table) { 25 | $table->renameColumn('company_id', 'companies_id'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | call(AdminAccSeeder::class); 17 | $this->call(FakerClientSeeder::class); 18 | $this->call(FakerCompaniesSeeder::class); 19 | $this->call(FakerEmployeesSeeder::class); 20 | $this->call(FakerDealsSeeder::class); 21 | $this->call(FakerProductsSeeder::class); 22 | $this->call(FakerSalesSeeder::class); 23 | $this->call(FakerTasksSeeder::class); 24 | $this->call(FakerFinancesSeeder::class); 25 | $this->call(SettingsSeeder::class); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Requests/ProductStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string', 28 | 'category' => 'required|string', 29 | 'count' => 'required|integer', 30 | 'price' => 'required|integer' 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2024_09_27_123343_rename_companies_id_to_company_id_in_finances_table.php: -------------------------------------------------------------------------------- 1 | renameColumn('companies_id', 'company_id'); 16 | }); 17 | } 18 | 19 | /** 20 | * Reverse the migrations. 21 | */ 22 | public function down(): void 23 | { 24 | Schema::table('finances', function (Blueprint $table) { 25 | $table->renameColumn('company_id', 'companies_id'); 26 | }); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /database/migrations/2024_11_26_104225_rename_tables.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class DealFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => $this->faker->name, 22 | 'start_time' => $this->faker->dateTime, 23 | 'end_time' => $this->faker->dateTime, 24 | 'company_id' => Company::get()->random()->id, 25 | 'is_active' => $this->faker->boolean, 26 | 'admin_id' => 1, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/factories/TaskFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class TaskFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => $this->faker->name, 22 | 'employee_id' => Employee::get()->random()->id, 23 | 'duration' => $this->faker->randomNumber(2), 24 | 'is_active' => $this->faker->boolean, 25 | 'completed' => $this->faker->boolean, 26 | 'admin_id' => 1, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have e-mailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that e-mail address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /app/Http/Requests/DealUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'name' => 'required|string', 29 | 'start_time' => 'required', 30 | 'end_time' => 'required', 31 | 'company_id' => 'required|integer', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Requests/SaleStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string', 28 | 'quantity' => 'required|integer', 29 | 'product_id' => 'required|integer', 30 | 'date_of_payment' => 'required', 31 | 'price' => 'required' 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Requests/ProductUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'name' => 'required|string', 29 | 'category' => 'required|string', 30 | 'count' => 'required|integer', 31 | 'price' => 'required|integer' 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/factories/SaleFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class SaleFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => $this->faker->name, 22 | 'quantity' => $this->faker->randomNumber(2), 23 | 'price' => $this->faker->randomFloat(2, 0, 1000), 24 | 'date_of_payment' => $this->faker->dateTimeThisYear(), 25 | 'product_id' => Product::get()->random()->id, 26 | 'admin_id' => 1, 27 | ]; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/Providers/EventServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | parent::boot(); 31 | 32 | // 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2024_10_17_083819_change_start_time_and_end_time_in_deals_table.php: -------------------------------------------------------------------------------- 1 | date('start_time')->change(); 16 | $table->date('end_time')->change(); 17 | }); 18 | } 19 | 20 | /** 21 | * Reverse the migrations. 22 | */ 23 | public function down(): void 24 | { 25 | Schema::table('deals', function (Blueprint $table) { 26 | $table->string('start_time')->change(); 27 | $table->string('end_time')->change(); 28 | }); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /app/Http/Requests/SettingsStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'pagination_size' => 'required|integer', 28 | 'currency' => 'required|string', 29 | 'priority_size' => 'required|integer', 30 | 'invoice_tax' => 'required|integer', 31 | 'loading_circle' => 'required' 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Requests/SaleUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'name' => 'required|string', 29 | 'quantity' => 'required|integer', 30 | 'product_id' => 'required|integer', 31 | 'date_of_payment' => 'required', 32 | 'price' => 'required' 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Requests/EmployeeStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'full_name' => 'required|string', 28 | 'phone' => 'required|string', 29 | 'email' => 'required|email', 30 | 'job' => 'required|string', 31 | 'note' => 'required|string', 32 | 'client_id' => 'required|integer' 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Requests/FinanceStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string', 28 | 'company_id' => 'required|integer', 29 | 'description' => 'required|string', 30 | 'type' => 'required|string', 31 | 'gross' => 'required|string', 32 | 'category' => 'required|string' 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Queries/FinanceQueries.php: -------------------------------------------------------------------------------- 1 | paginate(Setting::where('key', 'pagination_size') 34 | ->get()->last()->value); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/factories/EmployeeFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class EmployeeFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'full_name' => $this->faker->name, 22 | 'email' => $this->faker->unique()->safeEmail, 23 | 'phone' => $this->faker->phoneNumber, 24 | 'job' => $this->faker->jobTitle, 25 | 'note' => $this->faker->text, 26 | 'client_id' => Client::get()->random()->id, 27 | 'admin_id' => 1, 28 | 'is_active' => $this->faker->boolean, 29 | ]; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Http/Requests/EmployeeUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'full_name' => 'required|string', 29 | 'phone' => 'required|string', 30 | 'email' => 'required|email', 31 | 'job' => 'required|string', 32 | 'note' => 'required|string', 33 | 'client_id' => 'required|integer' 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2024_09_12_175506_create_sessions_table.php: -------------------------------------------------------------------------------- 1 | string('id')->primary(); 16 | $table->foreignId('user_id')->nullable()->index(); 17 | $table->string('ip_address', 45)->nullable(); 18 | $table->text('user_agent')->nullable(); 19 | $table->longText('payload'); 20 | $table->integer('last_activity')->index(); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | */ 27 | public function down(): void 28 | { 29 | Schema::dropIfExists('sessions'); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /app/Http/Requests/FinanceUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'name' => 'required|string', 29 | 'company_id' => 'required|integer', 30 | 'description' => 'required|string', 31 | 'type' => 'required|string', 32 | 'gross' => 'required|string', 33 | 'category' => 'required|string' 34 | ]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2020_01_19_131843_add_settings_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('key')->nullable(); 19 | $table->string('value')->nullable(); 20 | $table->string('description')->nullable(); 21 | $table->timestamps(); 22 | $table->dateTime('deleted_at')->nullable(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('settings'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2020_01_22_121759_add_deals_terms_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->longText('body'); 18 | $table->unsignedInteger('deal_id'); 19 | $table->foreign('deal_id')->references('id')->on('deals'); 20 | $table->timestamps(); 21 | $table->dateTime('deleted_at')->nullable(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('deals_terms'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Jobs/Deal/UpdateDealJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 26 | $this->deal = $deal; 27 | } 28 | 29 | /** 30 | * Execute the job. 31 | * 32 | * @return void 33 | */ 34 | public function handle(): void 35 | { 36 | $this->deal->update($this->validatedData); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Jobs/Sale/UpdateSaleJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 26 | $this->sale = $sale; 27 | } 28 | 29 | /** 30 | * Execute the job. 31 | * 32 | * @return void 33 | */ 34 | public function handle(): void 35 | { 36 | $this->sale->update($this->validatedData); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Services/FinancesService.php: -------------------------------------------------------------------------------- 1 | $net, 32 | 'vat' => $vat, 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Jobs/Task/UpdateTaskJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 27 | $this->task = $task; 28 | } 29 | 30 | /** 31 | * Execute the job. 32 | * 33 | * @return void 34 | */ 35 | public function handle(): void 36 | { 37 | $this->task->update($this->validatedData); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_admins_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->string('password'); 21 | $table->integer('role_type')->default(1); // default as a normal user 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('admins'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Jobs/Client/UpdateClientJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 27 | $this->client = $client; 28 | } 29 | 30 | /** 31 | * Execute the job. 32 | * 33 | * @return void 34 | */ 35 | public function handle(): void 36 | { 37 | $this->client->update($this->validatedData); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Jobs/Product/UpdateProductJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 26 | $this->product = $product; 27 | } 28 | 29 | /** 30 | * Execute the job. 31 | * 32 | * @return void 33 | */ 34 | public function handle(): void 35 | { 36 | $this->product->update($this->validatedData); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /database/migrations/2024_09_12_174147_create_cache_table.php: -------------------------------------------------------------------------------- 1 | string('key')->primary(); 16 | $table->mediumText('value'); 17 | $table->integer('expiration'); 18 | }); 19 | 20 | Schema::create('cache_locks', function (Blueprint $table) { 21 | $table->string('key')->primary(); 22 | $table->string('owner'); 23 | $table->integer('expiration'); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | */ 30 | public function down(): void 31 | { 32 | Schema::dropIfExists('cache'); 33 | Schema::dropIfExists('cache_locks'); 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /app/Jobs/Employee/UpdateEmployeeJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 26 | $this->employee = $employee; 27 | } 28 | 29 | /** 30 | * Execute the job. 31 | * 32 | * @return void 33 | */ 34 | public function handle(): void 35 | { 36 | $this->employee->update($this->validatedData); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Requests/ClientStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'full_name' => 'required|string', 28 | 'phone' => 'required|string', 29 | 'budget' => 'required|integer', 30 | 'section' => 'required|string', 31 | 'email' => 'required|email', 32 | 'location' => 'required|string', 33 | 'zip' => 'required|string', 34 | 'city' => 'required|string', 35 | 'country' => 'required|string' 36 | ]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | 31 | /** 32 | * Register the commands for the application. 33 | * 34 | * @return void 35 | */ 36 | protected function commands() 37 | { 38 | $this->load(__DIR__.'/Commands'); 39 | 40 | require base_path('routes/console.php'); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /database/factories/ClientFactory.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class ClientFactory extends Factory 11 | { 12 | /** 13 | * Define the model's default state. 14 | * 15 | * @return array 16 | */ 17 | public function definition(): array 18 | { 19 | return [ 20 | 'full_name' => $this->faker->name, 21 | 'phone' => $this->faker->phoneNumber, 22 | 'email' => $this->faker->unique()->safeEmail, 23 | 'section' => $this->faker->word, 24 | 'budget' => $this->faker->randomFloat(2, 1000, 100000), 25 | 'location' => $this->faker->word, 26 | 'zip' => $this->faker->postcode, 27 | 'city' => $this->faker->city, 28 | 'country' => $this->faker->country, 29 | 'is_active' => $this->faker->boolean, 30 | 'admin_id' => 1 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Jobs/Company/UpdateCompanyJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 28 | $this->company = $company; 29 | } 30 | 31 | /** 32 | * Execute the job. 33 | * 34 | * @return void 35 | */ 36 | public function handle(): void 37 | { 38 | $this->company->update($this->validatedData); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/Http/Requests/ClientUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'full_name' => 'required|string', 29 | 'phone' => 'required|string', 30 | 'budget' => 'required|integer', 31 | 'section' => 'required|string', 32 | 'email' => 'required|email', 33 | 'location' => 'required|string', 34 | 'zip' => 'required|string', 35 | 'city' => 'required|string', 36 | 'country' => 'required|string' 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /database/factories/FinanceFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class FinanceFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => $this->faker->name, 22 | 'company_id' => Company::get()->random()->id, 23 | 'category' => $this->faker->word, 24 | 'type' => $this->faker->word, 25 | 'date' => $this->faker->date(), 26 | 'gross' => $this->faker->randomFloat(), 27 | 'net' => $this->faker->randomFloat(), 28 | 'vat' => $this->faker->randomFloat(), 29 | 'description' => $this->faker->text, 30 | 'is_active' => $this->faker->boolean, 31 | 'admin_id' => 1 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Jobs/UpdateSettingsJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 26 | } 27 | 28 | /** 29 | * Execute the job. 30 | * 31 | * @return void 32 | */ 33 | public function handle(): void 34 | { 35 | foreach($this->validatedData as $key => $value) { 36 | Setting::where('key', $key)->update([ 37 | 'value' => $value, 38 | 'updated_at' => now() 39 | ]); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /MIT_License.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [year] [fullname] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /resources/views/layouts/components/forms/input.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | 15 |
16 |
17 | -------------------------------------------------------------------------------- /resources/views/layouts/components/forms/textarea.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | 15 |
16 |
17 | -------------------------------------------------------------------------------- /app/Queries/SystemLogQueries.php: -------------------------------------------------------------------------------- 1 | get()->last()->value); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Http/Requests/CompanyStoreRequest.php: -------------------------------------------------------------------------------- 1 | check(); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | return [ 27 | 'name' => 'required|string', 28 | 'tax_number' => 'required|integer', 29 | 'city' => 'required|string', 30 | 'billing_address' => 'required|string', 31 | 'country' => 'required|string', 32 | 'postal_code' => 'required|string', 33 | 'employees_size' => 'required|integer', 34 | 'fax' => 'required|string', 35 | 'description' => 'required|string', 36 | 'phone' => 'required|string', 37 | 'client_id' => 'required|integer', 38 | ]; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /database/migrations/2017_08_18_073557_create_table_deals.php: -------------------------------------------------------------------------------- 1 | increments('id'); 12 | $table->string('name'); 13 | $table->string('start_time'); 14 | $table->string('end_time'); 15 | $table->unsignedInteger('companies_id'); 16 | $table->foreign('companies_id')->references('id')->on('companies'); 17 | $table->boolean('is_active')->nullable()->default(1); 18 | $table->unsignedInteger('admin_id'); 19 | $table->foreign('admin_id')->references('id')->on('admins'); 20 | $table->timestamps(); 21 | $table->dateTime('deleted_at')->nullable(); 22 | }); 23 | } 24 | 25 | /** 26 | * Reverse the migrations. 27 | * 28 | * @return void 29 | */ 30 | public function down() 31 | { 32 | Schema::dropIfExists('deals'); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /database/migrations/2017_09_13_171236_create_table_products.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->string('category'); 19 | $table->integer('count'); 20 | $table->integer('price'); 21 | $table->boolean('is_active')->nullable()->default(1); 22 | $table->unsignedInteger('admin_id'); 23 | $table->foreign('admin_id')->references('id')->on('admins'); 24 | $table->timestamps(); 25 | $table->dateTime('deleted_at')->nullable(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('products'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'token' => env('POSTMARK_TOKEN'), 19 | ], 20 | 21 | 'ses' => [ 22 | 'key' => env('AWS_ACCESS_KEY_ID'), 23 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 24 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 25 | ], 26 | 27 | 'resend' => [ 28 | 'key' => env('RESEND_KEY'), 29 | ], 30 | 31 | 'slack' => [ 32 | 'notifications' => [ 33 | 'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'), 34 | 'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'), 35 | ], 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /app/Services/ClientService.php: -------------------------------------------------------------------------------- 1 | formattedBudget = Money::{SettingQueries::getSettingValue('currency')}($client->budget); 29 | 30 | return $client; 31 | } 32 | 33 | /** 34 | * Load the list of clients added in the latest month. 35 | * 36 | * @return float 37 | */ 38 | public function loadClientsInLatestMonth(): float 39 | { 40 | $clientsCountInLatestMonth = ClientQueries::getCountAllInLatestMonth(); 41 | $allClientCount = ClientQueries::getCountAll(); 42 | 43 | return ($clientsCountInLatestMonth / $allClientCount) * 100; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Http/Requests/CompanyUpdateRequest.php: -------------------------------------------------------------------------------- 1 | check(); 18 | } 19 | 20 | /** 21 | * Get the validation rules that apply to the request. 22 | * 23 | * @return array 24 | */ 25 | public function rules() 26 | { 27 | return [ 28 | 'name' => 'required|string', 29 | 'tax_number' => 'required|integer', 30 | 'city' => 'required|string', 31 | 'billing_address' => 'required|string', 32 | 'country' => 'required|string', 33 | 'postal_code' => 'required|string', 34 | 'employees_size' => 'required|integer', 35 | 'fax' => 'required|string', 36 | 'description' => 'required|string', 37 | 'phone' => 'required|string', 38 | 'client_id' => 'required|integer', 39 | ]; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2017_11_18_122319_SystemLogs.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('user_id')->nullable(); 18 | $table->string('actions')->nullable(); 19 | $table->integer('status_code')->nullable(); 20 | $table->string('ip_address')->nullable(); 21 | $table->string('city')->nullable(); 22 | $table->string('country')->nullable(); 23 | $table->dateTime('date')->nullable(); 24 | $table->unsignedInteger('admin_id'); 25 | $table->foreign('admin_id')->references('id')->on('admins'); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('mailing'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Models/Administrator.php: -------------------------------------------------------------------------------- 1 | 'datetime', 38 | ]; 39 | 40 | /** 41 | * Get user information by IP. 42 | * 43 | * @return mixed 44 | */ 45 | public function getUserInformation() 46 | { 47 | return unserialize(file_get_contents("http://www.geoplugin.net/php.gp?ip=$this->ip")); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Jobs/Client/StoreClientJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 28 | $this->admin = $admin; 29 | } 30 | 31 | /** 32 | * Execute the job. 33 | * 34 | * @return void 35 | */ 36 | public function handle() 37 | { 38 | $model = new Client(); 39 | 40 | foreach($this->validatedData as $key => $value) { 41 | $model->$key = $value; 42 | } 43 | 44 | $model->admin_id = $this->admin->id; 45 | 46 | $model->save(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Jobs/Product/StoreProductJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 28 | $this->admin = $admin; 29 | } 30 | 31 | /** 32 | * Execute the job. 33 | * 34 | * @return void 35 | */ 36 | public function handle(): void 37 | { 38 | $model = new Product(); 39 | 40 | foreach ($this->validatedData as $key => $value) { 41 | $model->$key = $value; 42 | } 43 | 44 | $model->admin_id = $this->admin->id; 45 | 46 | $model->save(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Jobs/Employee/StoreEmployeeJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 28 | $this->admin = $admin; 29 | } 30 | 31 | /** 32 | * Execute the job. 33 | * 34 | * @return void 35 | */ 36 | public function handle(): void 37 | { 38 | $model = new Employee(); 39 | 40 | foreach ($this->validatedData as $key => $value) { 41 | $model->$key = $value; 42 | } 43 | 44 | $model->admin_id = $this->admin->id; 45 | 46 | $model->save(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Queries/SaleQueries.php: -------------------------------------------------------------------------------- 1 | sortBy('created_at'); 33 | } 34 | 35 | /** 36 | * Get paginated list of sales. 37 | * 38 | * @return \Illuminate\Pagination\LengthAwarePaginator 39 | */ 40 | public static function getPaginate(): \Illuminate\Pagination\LengthAwarePaginator 41 | { 42 | return Sale::orderByDesc('id') 43 | ->paginate(Setting::where('key', 'pagination_size') 44 | ->get()->last()->value); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/Services/EmployeesService.php: -------------------------------------------------------------------------------- 1 | get(); 24 | 25 | foreach ($employees as $employee) { 26 | Arr::add($employee, 'taskCount', TaskQueries::getEmployeesTaskCount($employee->id)); 27 | } 28 | 29 | return $employees; 30 | } 31 | 32 | /** 33 | * Load the list of employees added in the latest month. 34 | * 35 | * @return int 36 | */ 37 | public function loadEmployeesInLatestMonth(): int 38 | { 39 | $employeesCountInLatestMonth = EmployeeQueries::getEmployeesInLatestMonth(); 40 | $allEmployees = EmployeeQueries::countAll(); 41 | 42 | return (int) (($employeesCountInLatestMonth / $allEmployees) * 100); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Jobs/Deal/StoreDealTermJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 29 | $this->deal = $deal; 30 | } 31 | 32 | /** 33 | * Execute the job. 34 | * 35 | * @return void 36 | */ 37 | public function handle(): void 38 | { 39 | $model = new DealTerm(); 40 | 41 | foreach ($this->validatedData as $key => $value) { 42 | $model->$key = $value; 43 | } 44 | 45 | 46 | $model->deal_id = $this->deal->id; 47 | 48 | $model->save(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /database/factories/CompanyFactory.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class CompanyFactory extends Factory 12 | { 13 | /** 14 | * Define the model's default state. 15 | * 16 | * @return array 17 | */ 18 | public function definition(): array 19 | { 20 | return [ 21 | 'name' => $this->faker->name, 22 | 'tax_number' => $this->faker->randomNumber(8), 23 | 'phone' => $this->faker->phoneNumber, 24 | 'city' => $this->faker->city, 25 | 'billing_address' => $this->faker->address, 26 | 'country' => $this->faker->country, 27 | 'postal_code' => $this->faker->postcode, 28 | 'employees_size' => $this->faker->randomNumber(3), 29 | 'fax' => $this->faker->phoneNumber, 30 | 'description' => $this->faker->text, 31 | 'client_id' => Client::get()->random()->id, 32 | 'admin_id' => 1, 33 | 'created_at' => $this->faker->dateTime, 34 | 'is_active' => $this->faker->boolean, 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2017_08_08_063939_create_table_clients.php: -------------------------------------------------------------------------------- 1 | increments('id'); 12 | $table->string('full_name'); 13 | $table->string('phone'); 14 | $table->string('email', 255); 15 | $table->text('section'); 16 | $table->text('budget'); 17 | $table->text('location'); 18 | $table->text('zip'); 19 | $table->text('city'); 20 | $table->text('country'); 21 | $table->boolean('is_active')->nullable()->default(1); 22 | $table->unsignedInteger('admin_id'); 23 | $table->foreign('admin_id')->references('id')->on('admins'); 24 | $table->timestamps(); 25 | $table->dateTime('deleted_at')->nullable(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('clients'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Jobs/Deal/StoreDealJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 29 | $this->admin = $admin; 30 | } 31 | 32 | /** 33 | * Execute the job. 34 | * 35 | * @return void 36 | */ 37 | public function handle(): void 38 | { 39 | $model = new Deal(); 40 | 41 | foreach ($this->validatedData as $key => $value) { 42 | $model->$key = $value; 43 | } 44 | 45 | $model->admin_id = $this->admin->id; 46 | 47 | $model->save(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Jobs/Sale/StoreSaleJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 29 | $this->admin = $admin; 30 | } 31 | 32 | /** 33 | * Execute the job. 34 | * 35 | * @return void 36 | */ 37 | public function handle(): void 38 | { 39 | $model = new Sale(); 40 | 41 | foreach ($this->validatedData as $key => $value) { 42 | $model->$key = $value; 43 | } 44 | 45 | $model->admin_id = $this->admin->id; 46 | 47 | $model->save(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Jobs/Task/StoreTaskJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 29 | $this->admin = $admin; 30 | } 31 | 32 | /** 33 | * Execute the job. 34 | * 35 | * @return void 36 | */ 37 | public function handle(): void 38 | { 39 | $model = new Task(); 40 | 41 | foreach ($this->validatedData as $key => $value) { 42 | $model->$key = $value; 43 | } 44 | 45 | $model->admin_id = $this->admin->id; 46 | 47 | $model->save(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /database/migrations/2017_09_12_124214_create_table_tasks.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->text('name'); 18 | $table->unsignedInteger('employee_id'); 19 | $table->foreign('employee_id')->references('id')->on('employees'); 20 | $table->integer('duration'); 21 | $table->boolean('is_active')->nullable()->default(1); 22 | $table->boolean('completed')->nullable()->default(0); 23 | $table->unsignedInteger('admin_id'); 24 | $table->foreign('admin_id')->references('id')->on('admins'); 25 | $table->timestamps(); 26 | $table->dateTime('deleted_at')->nullable(); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('tasks'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | tests/Unit 10 | 11 | 12 | tests/Feature 13 | 14 | 15 | 16 | 17 | app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/Jobs/Company/StoreCompanyJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 29 | $this->admin = $admin; 30 | } 31 | 32 | /** 33 | * Execute the job. 34 | * 35 | * @return void 36 | */ 37 | public function handle(): void 38 | { 39 | $model = new Company(); 40 | 41 | foreach ($this->validatedData as $key => $value) { 42 | $model->$key = $value; 43 | } 44 | 45 | $model->admin_id = $this->admin->id; 46 | 47 | $model->save(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /app/Services/DealsService.php: -------------------------------------------------------------------------------- 1 | count() / $allDeals) * 100); 28 | } 29 | 30 | /** 31 | * Generate a PDF of deal terms. 32 | * 33 | * @param DealTerm $dealTerm The deal terms to be included in the PDF. 34 | * @param Deal $deal The deal associated with the terms. 35 | * @return \Illuminate\Http\Response 36 | */ 37 | public function loadGenerateDealTermsInPDF(DealTerm $dealTerm, Deal $deal): \Illuminate\Http\Response 38 | { 39 | $data = ['body' => $dealTerm->body]; 40 | 41 | return PDF::loadView('crm.deals.terms.terms_pdf', $data) 42 | ->download($deal->name . '.pdf'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /database/migrations/2017_09_13_171248_create_table_sales.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->integer('quantity'); 19 | $table->integer('price'); 20 | $table->date('date_of_payment'); 21 | $table->unsignedInteger('product_id'); 22 | $table->foreign('product_id')->references('id')->on('products'); 23 | $table->boolean('is_active')->nullable()->default(1); 24 | $table->unsignedInteger('admin_id'); 25 | $table->foreign('admin_id')->references('id')->on('admins'); 26 | $table->timestamps(); 27 | $table->dateTime('deleted_at')->nullable(); 28 | }); 29 | } 30 | 31 | /** 32 | * Reverse the migrations. 33 | * 34 | * @return void 35 | */ 36 | public function down() 37 | { 38 | Schema::dropIfExists('sales'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /resources/views/layouts/components/forms/select.blade.php: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /database/migrations/2017_09_13_171158_create_table_reports.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->unsignedInteger('companies_id'); 19 | $table->foreign('companies_id')->references('id')->on('companies'); 20 | $table->unsignedInteger('clients_id'); 21 | $table->foreign('clients_id')->references('id')->on('clients'); 22 | $table->boolean('is_active')->nullable()->default(1); 23 | $table->unsignedInteger('admin_id'); 24 | $table->foreign('admin_id')->references('id')->on('admins'); 25 | $table->timestamps(); 26 | $table->dateTime('deleted_at')->nullable(); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('reports'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME=Laravel 2 | APP_ENV=local 3 | APP_KEY= 4 | APP_DEBUG=true 5 | APP_TIMEZONE=UTC 6 | APP_URL=http://localhost 7 | 8 | APP_LOCALE=en 9 | APP_FALLBACK_LOCALE=en 10 | APP_FAKER_LOCALE=en_US 11 | 12 | APP_MAINTENANCE_DRIVER=file 13 | # APP_MAINTENANCE_STORE=database 14 | 15 | BCRYPT_ROUNDS=12 16 | 17 | LOG_CHANNEL=stack 18 | LOG_STACK=single 19 | LOG_DEPRECATIONS_CHANNEL=null 20 | LOG_LEVEL=debug 21 | 22 | DB_CONNECTION=sqlite 23 | # DB_HOST=127.0.0.1 24 | # DB_PORT=3306 25 | # DB_DATABASE=laravel 26 | # DB_USERNAME=root 27 | # DB_PASSWORD= 28 | 29 | SESSION_DRIVER=database 30 | SESSION_LIFETIME=120 31 | SESSION_ENCRYPT=false 32 | SESSION_PATH=/ 33 | SESSION_DOMAIN=null 34 | 35 | BROADCAST_CONNECTION=log 36 | FILESYSTEM_DISK=local 37 | QUEUE_CONNECTION=database 38 | 39 | CACHE_STORE=database 40 | CACHE_PREFIX= 41 | 42 | MEMCACHED_HOST=127.0.0.1 43 | 44 | REDIS_CLIENT=phpredis 45 | REDIS_HOST=127.0.0.1 46 | REDIS_PASSWORD=null 47 | REDIS_PORT=6379 48 | 49 | MAIL_MAILER=log 50 | MAIL_HOST=127.0.0.1 51 | MAIL_PORT=2525 52 | MAIL_USERNAME=null 53 | MAIL_PASSWORD=null 54 | MAIL_ENCRYPTION=null 55 | MAIL_FROM_ADDRESS="hello@example.com" 56 | MAIL_FROM_NAME="${APP_NAME}" 57 | 58 | AWS_ACCESS_KEY_ID= 59 | AWS_SECRET_ACCESS_KEY= 60 | AWS_DEFAULT_REGION=us-east-1 61 | AWS_BUCKET= 62 | AWS_USE_PATH_STYLE_ENDPOINT=false 63 | 64 | VITE_APP_NAME="${APP_NAME}" 65 | -------------------------------------------------------------------------------- /database/migrations/2017_08_19_101613_create_table_Employees.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('full_name'); 18 | $table->string('phone'); 19 | $table->string('email'); 20 | $table->string('job'); 21 | $table->text('note'); 22 | $table->unsignedInteger('client_id'); 23 | $table->foreign('client_id')->references('id')->on('clients'); 24 | $table->boolean('is_active')->nullable()->default(1); 25 | $table->unsignedInteger('admin_id'); 26 | $table->foreign('admin_id')->references('id')->on('admins'); 27 | $table->timestamps(); 28 | $table->dateTime('deleted_at')->nullable(); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('employees'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/Jobs/ChangePasswordJob.php: -------------------------------------------------------------------------------- 1 | oldPassword = $validatedData['old_password']; 30 | $this->newPassword = $validatedData['new_password']; 31 | $this->confirmNewPassword = $validatedData['confirm_password']; 32 | 33 | $this->adminModel = $adminModel; 34 | } 35 | 36 | /** 37 | * Execute the job. 38 | * 39 | * @return void 40 | */ 41 | public function handle(): void 42 | { 43 | $this->adminModel->update([ 44 | 'password' => Hash::make($this->newPassword), 45 | 'updated_at' => now() 46 | ]); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /resources/views/crm/auth/login.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @include('layouts.head', ['title' => 'Login']) 4 | 5 |
6 | @include('layouts.flash-messages') 7 |

SoftCRM

8 |
9 | {{ csrf_field() }} 10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /app/Jobs/Finance/UpdateFinanceJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 28 | $this->finance = $finance; 29 | } 30 | 31 | /** 32 | * Execute the job. 33 | * 34 | * @return void 35 | */ 36 | public function handle(): void 37 | { 38 | if(isset($this->validatedData['gross'])) { 39 | $financesHelper = new FinancesService(); 40 | $dataToInsert = $financesHelper->loadCalculateNetAndVatByGivenGross($this->validatedData['gross']); 41 | 42 | $this->validatedData['net'] = $dataToInsert['net']; 43 | $this->validatedData['vat'] = $dataToInsert['vat']; 44 | } 45 | 46 | $this->finance->update($this->validatedData); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Services/TasksService.php: -------------------------------------------------------------------------------- 1 | =', now()->subMonth())->get(); 23 | } 24 | 25 | /** 26 | * Get the count of all deals. 27 | * 28 | * @return int 29 | */ 30 | public static function countAll(): int 31 | { 32 | return Deal::all()->count(); 33 | } 34 | 35 | /** 36 | * Get the count of all deactivated deals. 37 | * 38 | * @return int 39 | */ 40 | public static function getDeactivated(): int 41 | { 42 | return Deal::where('is_active', '=', 0)->count(); 43 | } 44 | 45 | /** 46 | * Get paginated list of deals. 47 | * 48 | * @return \Illuminate\Pagination\LengthAwarePaginator 49 | */ 50 | public static function getPaginate(): \Illuminate\Pagination\LengthAwarePaginator 51 | { 52 | return Deal::orderByDesc('id') 53 | ->paginate(Setting::where('key', 'pagination_size') 54 | ->get()->last()->value); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/Queries/EmployeeQueries.php: -------------------------------------------------------------------------------- 1 | count(); 23 | } 24 | 25 | /** 26 | * Get the percentage of employees created in the latest month. 27 | * 28 | * @return float 29 | */ 30 | public static function getEmployeesInLatestMonth(): float 31 | { 32 | return Employee::where('created_at', '>=', now()->subMonth())->count(); 33 | } 34 | 35 | /** 36 | * Get the count of all employees. 37 | * 38 | * @return int 39 | */ 40 | public static function countAll(): int 41 | { 42 | return Employee::all()->count(); 43 | } 44 | 45 | /** 46 | * Get paginated list of employees. 47 | * 48 | * @return \Illuminate\Pagination\LengthAwarePaginator 49 | */ 50 | public static function getPaginate(): \Illuminate\Pagination\LengthAwarePaginator 51 | { 52 | return Employee::orderByDesc('id') 53 | ->paginate(Setting::where('key', 'pagination_size') 54 | ->get()->last()->value); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /bootstrap/cache/packages.php: -------------------------------------------------------------------------------- 1 | 3 | array ( 4 | 'providers' => 5 | array ( 6 | 0 => 'Barryvdh\\DomPDF\\ServiceProvider', 7 | ), 8 | 'aliases' => 9 | array ( 10 | 'Pdf' => 'Barryvdh\\DomPDF\\Facade\\Pdf', 11 | 'PDF' => 'Barryvdh\\DomPDF\\Facade\\Pdf', 12 | ), 13 | ), 14 | 'cknow/laravel-money' => 15 | array ( 16 | 'providers' => 17 | array ( 18 | 0 => 'Cknow\\Money\\MoneyServiceProvider', 19 | ), 20 | ), 21 | 'icehouse-ventures/laravel-chartjs' => 22 | array ( 23 | 'providers' => 24 | array ( 25 | 0 => 'IcehouseVentures\\LaravelChartjs\\Providers\\ChartjsServiceProvider', 26 | ), 27 | 'aliases' => 28 | array ( 29 | 'Chartjs' => 'IcehouseVentures\\LaravelChartjs\\Facades\\Chartjs', 30 | ), 31 | ), 32 | 'laravel/tinker' => 33 | array ( 34 | 'providers' => 35 | array ( 36 | 0 => 'Laravel\\Tinker\\TinkerServiceProvider', 37 | ), 38 | ), 39 | 'nesbot/carbon' => 40 | array ( 41 | 'providers' => 42 | array ( 43 | 0 => 'Carbon\\Laravel\\ServiceProvider', 44 | ), 45 | ), 46 | 'nunomaduro/collision' => 47 | array ( 48 | 'providers' => 49 | array ( 50 | 0 => 'NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider', 51 | ), 52 | ), 53 | 'nunomaduro/termwind' => 54 | array ( 55 | 'providers' => 56 | array ( 57 | 0 => 'Termwind\\Laravel\\TermwindServiceProvider', 58 | ), 59 | ), 60 | ); -------------------------------------------------------------------------------- /app/Queries/ProductQueries.php: -------------------------------------------------------------------------------- 1 | get(); 33 | } 34 | 35 | /** 36 | * Get paginated list of products. 37 | * 38 | * @return \Illuminate\Pagination\LengthAwarePaginator 39 | */ 40 | public static function getPaginate(): \Illuminate\Pagination\LengthAwarePaginator 41 | { 42 | return Product::orderByDesc('id') 43 | ->paginate(Setting::where('key', 'pagination_size') 44 | ->get()->last()->value); 45 | } 46 | 47 | /** 48 | * Get all products. 49 | * 50 | * @return \Illuminate\Database\Eloquent\Collection 51 | */ 52 | public static function getAll(): \Illuminate\Database\Eloquent\Collection 53 | { 54 | return Product::all(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /database/migrations/2017_08_08_063944_create_table_companies.php: -------------------------------------------------------------------------------- 1 | increments('id'); 12 | $table->string('name', 255); 13 | $table->string('tax_number'); 14 | $table->string('phone'); 15 | $table->string('city', 255); 16 | $table->string('billing_address', 255); 17 | $table->string('country', 255); 18 | $table->string('postal_code', 64); 19 | $table->string('employees_size', 255); 20 | $table->string('fax'); 21 | $table->string('description', 255); 22 | $table->boolean('is_active')->nullable()->default(1); 23 | $table->unsignedInteger('client_id'); 24 | $table->foreign('client_id')->references('id')->on('clients'); 25 | $table->unsignedInteger('admin_id'); 26 | $table->foreign('admin_id')->references('id')->on('admins'); 27 | $table->timestamps(); 28 | $table->dateTime('deleted_at')->nullable(); 29 | }); 30 | } 31 | 32 | /** 33 | * Reverse the migrations. 34 | * 35 | * @return void 36 | */ 37 | public function down() 38 | { 39 | Schema::dropIfExists('companies'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /database/migrations/2017_09_13_171227_create_table_finances.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->string('description'); 19 | $table->string('category'); 20 | $table->string('type'); 21 | $table->integer('gross'); 22 | $table->integer('net')->nullable()->default(0); 23 | $table->integer('vat')->nullable()->default(0); 24 | $table->date('date'); 25 | $table->unsignedInteger('companies_id'); 26 | $table->foreign('companies_id')->references('id')->on('companies'); 27 | $table->boolean('is_active')->nullable()->default(1); 28 | $table->unsignedInteger('admin_id'); 29 | $table->foreign('admin_id')->references('id')->on('admins'); 30 | $table->timestamps(); 31 | $table->dateTime('deleted_at')->nullable(); 32 | }); 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::dropIfExists('finances'); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/Jobs/Finance/StoreFinanceJob.php: -------------------------------------------------------------------------------- 1 | validatedData = $validatedData; 29 | $this->admin = $admin; 30 | } 31 | 32 | /** 33 | * Execute the job. 34 | * 35 | * @return void 36 | */ 37 | public function handle(): void 38 | { 39 | $financesHelper = new FinancesService(); 40 | $dataToInsert = $financesHelper->loadCalculateNetAndVatByGivenGross($this->validatedData['gross']); 41 | 42 | $model = new Finance(); 43 | 44 | foreach ($this->validatedData as $key => $value) { 45 | $model->$key = $value; 46 | } 47 | 48 | $model->admin_id = $this->admin->id; 49 | 50 | $model->net = $dataToInsert['net']; 51 | $model->vat = $dataToInsert['vat']; 52 | 53 | $model->date = now(); 54 | 55 | $model->save(); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/Jobs/StoreSystemLogJob.php: -------------------------------------------------------------------------------- 1 | actions = $actions; 29 | $this->statusCode = $statusCode; 30 | $this->authUser = $authUser; 31 | } 32 | 33 | /** 34 | * Execute the job. 35 | * 36 | * @return void 37 | */ 38 | public function handle(): void 39 | { 40 | $userInformation = $this->authUser->getUserInformation(); 41 | 42 | $model = new SystemLog(); 43 | 44 | $model->admin_id = $this->authUser->id; 45 | $model->actions = $this->actions; 46 | $model->status_code = $this->statusCode; 47 | $model->date = now(); 48 | $model->ip_address = $userInformation['geoplugin_request']; 49 | $model->city = $userInformation['geoplugin_city']; 50 | $model->country = $userInformation['geoplugin_countryName']; 51 | 52 | $model->save(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /app/Queries/ClientQueries.php: -------------------------------------------------------------------------------- 1 | paginate(Setting::where('key', 'pagination_size') 34 | ->get()->last()->value); 35 | } 36 | 37 | /** 38 | * Get the count of all deactivated clients. 39 | * 40 | * @return int 41 | */ 42 | public static function getDeactivated(): int 43 | { 44 | return Client::where('is_active', '=', 0)->count(); 45 | } 46 | 47 | /** 48 | * Get the count of all clients. 49 | * 50 | * @return int 51 | */ 52 | public static function getCountAll(): int 53 | { 54 | return Client::all()->count(); 55 | } 56 | 57 | /** 58 | * Get the count of all clients created in the latest month. 59 | * 60 | * @return int 61 | */ 62 | public static function getCountAllInLatestMonth(): int 63 | { 64 | return Client::where('created_at', '>=', now()->subMonth())->count(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /resources/views/layouts/header.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 8 |
9 |
10 | 19 |
20 | Settings 21 | Password reset 22 | Logout 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /resources/views/layouts/head.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ $title }} - SoftCRM 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 39 | 40 |
41 | 56 | -------------------------------------------------------------------------------- /app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | mapApiRoutes(); 46 | 47 | $this->mapWebRoutes(); 48 | 49 | // 50 | } 51 | 52 | /** 53 | * Define the "web" routes for the application. 54 | * 55 | * These routes all receive session state, CSRF protection, etc. 56 | * 57 | * @return void 58 | */ 59 | protected function mapWebRoutes() 60 | { 61 | Route::middleware('web') 62 | ->namespace($this->namespace) 63 | ->group(base_path('routes/web.php')); 64 | } 65 | 66 | /** 67 | * Define the "api" routes for the application. 68 | * 69 | * These routes are typically stateless. 70 | * 71 | * @return void 72 | */ 73 | protected function mapApiRoutes() 74 | { 75 | Route::prefix('api') 76 | ->middleware('api') 77 | ->namespace($this->namespace) 78 | ->group(base_path('routes/api.php')); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/Console/Commands/processSoftCRM.php: -------------------------------------------------------------------------------- 1 | info('Welcome in SoftCRM!'); 46 | 47 | $this->info('==============================================================='); 48 | $this->info('[Let\'s start process all migrations:]'); 49 | $this->call('migrate'); 50 | 51 | $this->info('==============================================================='); 52 | $this->info('[Let\'s start process all seeders:]'); 53 | $this->call('db:seed'); 54 | 55 | $this->info('==============================================================='); 56 | $this->info('[Let\'s start process generating unique key:]'); 57 | $this->call('key:generate'); 58 | 59 | $this->info('==============================================================='); 60 | $this->info('Everything looks perfect! Now you can start use SoftCRM!'); 61 | $this->info('If you have any question please contact with me by email: kamil.grzechulskii@gmail.com'); 62 | 63 | $this->dispatchSync(new StoreSystemLogJob('First usage of process-softcrm command', 200, 1)); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/Http/Controllers/CRM/SettingsController.php: -------------------------------------------------------------------------------- 1 | with([ 30 | 'settings' => SettingQueries::getAll(), 31 | 'logs' => SystemLogQueries::getPaginate() 32 | ]); 33 | } 34 | 35 | /** 36 | * Update settings based on the provided request. 37 | * 38 | * @param SettingsStoreRequest $request 39 | * @return \Illuminate\Http\RedirectResponse 40 | * @throws \Exception 41 | */ 42 | public function processUpdateSettings(SettingsStoreRequest $request): \Illuminate\Http\RedirectResponse 43 | { 44 | // Validate the incoming request using the SettingsStoreRequest 45 | $validatedData = $request->validated(); 46 | 47 | // Dispatch the UpdateSettingsJob to update the settings 48 | $this->dispatchSync(new UpdateSettingsJob($validatedData)); 49 | 50 | // Dispatch the StoreSystemLogJob to store the system log 51 | $this->dispatchSync(new StoreSystemLogJob('SettingsModel has been changed.', 201, auth()->user())); 52 | 53 | //forgot cache of loading circle 54 | cache()->forget('loadingCircle'); 55 | 56 | // Redirect back with a success message 57 | return redirect()->back()->with('message_success', $this->getMessage('messages.settings_update')); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /resources/views/layouts/components/stats.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 |
6 |

Clients: {{ cache()->get('countClients') }} ({{ cache()->get('deactivatedClients') }})

7 |

{{ cache()->get('clientsInLatestMonth') }}% increase in 30 days.

8 |
9 |
10 |
11 | 12 |
13 |
14 | 15 |
16 |

Companies: {{ cache()->get('countCompanies') }} ({{ cache()->get('deactivatedCompanies') }})

17 |

{{ cache()->get('companiesInLatestMonth') }}%% increase in 30 days.

18 |
19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |

Employees: {{ cache()->get('countFinances') }}({{ cache()->get('deactivatedEmployees') }})

27 |

{{ cache()->get('employeesInLatestMonth') }}% increase in 30 days.

28 |
29 |
30 |
31 | 32 |
33 |
34 | 35 |
36 |

Deals: {{ cache()->get('countDeals') }} ({{ cache()->get('deactivatedDeals') }})

37 |

{{ cache()->get('dealsInLatestMonth') }}% increase in 30 days.

38 |
39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /app/Queries/CompanyQueries.php: -------------------------------------------------------------------------------- 1 | sortBy('created_at'); 23 | } 24 | 25 | /** 26 | * Get paginated list of companies. 27 | * 28 | * @return \Illuminate\Pagination\LengthAwarePaginator 29 | */ 30 | public static function getPaginate(): \Illuminate\Pagination\LengthAwarePaginator 31 | { 32 | return Company::orderByDesc('id') 33 | ->paginate(Setting::where('key', 'pagination_size') 34 | ->get()->last()->value); 35 | } 36 | 37 | /** 38 | * Get the count of all deactivated companies. 39 | * 40 | * @return int 41 | */ 42 | public static function getDeactivated(): int 43 | { 44 | return Company::where('is_active', '=', 0)->count(); 45 | } 46 | 47 | /** 48 | * Get companies sorted by creation date. 49 | * 50 | * @return \Illuminate\Support\Collection 51 | */ 52 | public static function getCompaniesSortedByCreatedAt(): \Illuminate\Support\Collection 53 | { 54 | return Company::all()->sortBy('created_at', 0, true)->slice(0, 5); 55 | } 56 | 57 | /** 58 | * Get the count of all companies. 59 | * 60 | * @return int 61 | */ 62 | public static function countAll(): int 63 | { 64 | return Company::all()->count(); 65 | } 66 | 67 | /** 68 | * Get the count of all companies created in the latest month. 69 | * 70 | * @return int 71 | */ 72 | public static function getCompaniesInLatestMonth(): int 73 | { 74 | return Company::where('created_at', '>=', now()->subMonth())->count(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": [ 6 | "framework", 7 | "laravel" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": "^8.2.14", 12 | "laravel/framework": "^11.27.2", 13 | "laravel/tinker": "^2.9" 14 | }, 15 | "require-dev": { 16 | "barryvdh/laravel-dompdf": "^v3.0.0", 17 | "cknow/laravel-money": "^v8.1.0", 18 | "fakerphp/faker": "^1.24", 19 | "icehouse-ventures/laravel-chartjs": "^4.0", 20 | "laravel/pint": "^1.13", 21 | "mockery/mockery": "^1.6", 22 | "nunomaduro/collision": "v8.1", 23 | "phpunit/phpunit": "^11.0.1" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "App\\": "app/", 28 | "Database\\Factories\\": "database/factories/", 29 | "Database\\Seeders\\": "database/seeders/", 30 | "App\\Enums\\": "app/Enums/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Tests\\": "tests/" 36 | } 37 | }, 38 | "scripts": { 39 | "post-autoload-dump": [ 40 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 41 | "@php artisan package:discover --ansi" 42 | ], 43 | "post-update-cmd": [ 44 | "@php artisan vendor:publish --tag=laravel-assets --ansi --force" 45 | ], 46 | "post-root-package-install": [ 47 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 48 | ], 49 | "post-create-project-cmd": [ 50 | "@php artisan key:generate --ansi", 51 | "@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"", 52 | "@php artisan migrate --graceful --ansi" 53 | ] 54 | }, 55 | "extra": { 56 | "laravel": { 57 | "dont-discover": [] 58 | } 59 | }, 60 | "config": { 61 | "optimize-autoloader": true, 62 | "preferred-install": "dist", 63 | "sort-packages": true, 64 | "allow-plugins": { 65 | "pestphp/pest-plugin": true, 66 | "php-http/discovery": true 67 | } 68 | }, 69 | "minimum-stability": "stable", 70 | "prefer-stable": true 71 | } 72 | -------------------------------------------------------------------------------- /resources/views/crm/deals/terms/create.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @include('layouts.head', ['title' => 'Add new deal']) 4 | 5 | 6 |
7 | @include('layouts.sidebar') 8 | 9 |
10 | @include('layouts.header') 11 | 12 |
13 |
14 | @include('layouts.flash-messages') 15 |
16 | 17 |
18 |
19 |

Add new deal term

20 | 21 | 24 | 25 |
26 |
27 | 28 |
29 |
30 |
31 | @csrf 32 |
33 |
34 | @include('layouts.components.forms.textarea', [ 35 | 'name' => 'Body', 36 | 'inputId' => 'body', 37 | 'inputName' => 'body', 38 | 'inputType' => 'text', 39 | 'inputRequired' => true 40 | ]) 41 |
42 |
43 | 44 |
45 | 46 |
47 |
48 |
49 |
50 | 51 |
52 | 53 | @include('layouts.footer') 54 |
55 |
56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /resources/lang/en/messages.php: -------------------------------------------------------------------------------- 1 | 'Please write something here...', 7 | 'cache_reload' => 'Information has been reloaded.', 8 | 9 | /** Clients Messages **/ 10 | 'client_store' => 'Client has been added.', 11 | 'client_update' => 'Client has been updated.', 12 | 'client_delete' => 'Client has been deleted.', 13 | 'settings_update' => 'Settings has been updated.', 14 | 15 | /** Companies Messages **/ 16 | 'companies_store' => 'Company has been added.', 17 | 'companies_update' => 'Company has been updated.', 18 | 'companies_delete' => 'Company has been deleted.', 19 | 'first_delete_companies' => 'Cannot delete this company, have assigned companies.', 20 | 'first_delete_employees' => 'Cannot delete this company, have assigned employees.', 21 | 'first_delete_deals' => 'Cannot delete company, have assigned deals.', 22 | 23 | /** Deals Messages **/ 24 | 'deal_store' => 'Deal has been added.', 25 | 'deal_term_store' => 'Deal term has been added.', 26 | 'deal_update' => 'Deal has been updated.', 27 | 'deal_delete' => 'Deal has been deleted.', 28 | 'deal_term_delete' => 'Deal term has been deleted.', 29 | 'deal_first_delete_deal|_term' => 'Please delete first deal terms.', 30 | 31 | /** Employees Messages **/ 32 | 'employee_store' => 'Employee has been added.', 33 | 'employee_update' => 'Employee has been updated.', 34 | 'employee_delete' => 'Employee has been deleted.', 35 | 'task_delete_tasks' => 'You cannot delete this employee that has been assigned a tasks.', 36 | 37 | /** Tasks Messages **/ 38 | 'task_completed' => 'Task successfully completed.', 39 | 'task_delete' => 'Task has been deleted.', 40 | 'task_store' => 'Task has been added.', 41 | 'task_update' => 'Task has been updated.', 42 | 'task_uncompleted' => 'Task hasn\'t been completed yet.', 43 | 44 | /** Sales Messages **/ 45 | 'sale_store' => 'Sales has been added.', 46 | 'sale_delete' => 'Sales has been deleted.', 47 | 'sale_update' => 'Sales has been updated.', 48 | 49 | /** Finances Messages **/ 50 | 'finance_store' => 'Finances has been added.', 51 | 'finance_delete' => 'Finances has been deleted.', 52 | 'finance_update' => 'Finances has been updated.', 53 | 54 | /** Products Messages **/ 55 | 'product_store' => 'Product has been added.', 56 | 'product_delete' => 'Product has been deleted.', 57 | 'product_update' => 'Product has been deactivated.', 58 | 'product_first_delete_sales' => 'Cannot delete this product, have assigned sales.', 59 | ]; 60 | -------------------------------------------------------------------------------- /config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DISK', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Filesystem Disks 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Below you may configure as many filesystem disks as necessary, and you 24 | | may even configure multiple disks for the same driver. Examples for 25 | | most supported storage drivers are configured here for reference. 26 | | 27 | | Supported drivers: "local", "ftp", "sftp", "s3" 28 | | 29 | */ 30 | 31 | 'disks' => [ 32 | 33 | 'local' => [ 34 | 'driver' => 'local', 35 | 'root' => storage_path('app/private'), 36 | 'serve' => true, 37 | 'throw' => false, 38 | ], 39 | 40 | 'public' => [ 41 | 'driver' => 'local', 42 | 'root' => storage_path('app/public'), 43 | 'url' => env('APP_URL').'/storage', 44 | 'visibility' => 'public', 45 | 'throw' => false, 46 | ], 47 | 48 | 's3' => [ 49 | 'driver' => 's3', 50 | 'key' => env('AWS_ACCESS_KEY_ID'), 51 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 52 | 'region' => env('AWS_DEFAULT_REGION'), 53 | 'bucket' => env('AWS_BUCKET'), 54 | 'url' => env('AWS_URL'), 55 | 'endpoint' => env('AWS_ENDPOINT'), 56 | 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 57 | 'throw' => false, 58 | ], 59 | 60 | ], 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Symbolic Links 65 | |-------------------------------------------------------------------------- 66 | | 67 | | Here you may configure the symbolic links that will be created when the 68 | | `storage:link` Artisan command is executed. The array keys should be 69 | | the locations of the links and the values should be their targets. 70 | | 71 | */ 72 | 73 | 'links' => [ 74 | public_path('storage') => storage_path('app/public'), 75 | ], 76 | 77 | ]; 78 | -------------------------------------------------------------------------------- /app/Queries/TaskQueries.php: -------------------------------------------------------------------------------- 1 | paginate(Setting::where('key', 'pagination_size') 26 | ->get()->last()->value); 27 | } 28 | 29 | /** 30 | * Get the count of all tasks. 31 | * 32 | * @return int 33 | */ 34 | public static function countAll(): int 35 | { 36 | return Task::count(); 37 | } 38 | 39 | /** 40 | * Get the count of all completed tasks. 41 | * 42 | * @return int 43 | */ 44 | public static function getCountCompleted(): int 45 | { 46 | return Task::where('completed', '=', 1) 47 | ->count(); 48 | } 49 | 50 | /** 51 | * Get the count of all uncompleted tasks. 52 | * 53 | * @return int 54 | */ 55 | public static function getAllUncompletedTasks(): int 56 | { 57 | return Task::where('completed', '=', 0) 58 | ->count(); 59 | } 60 | 61 | /** 62 | * Get the count of tasks assigned to a specific employee. 63 | * 64 | * @param mixed $id The ID of the employee. 65 | * @return int 66 | */ 67 | public static function getEmployeesTaskCount(mixed $id): int 68 | { 69 | return Task::where('employee_id', $id)->get()->count(); 70 | } 71 | 72 | /** 73 | * Get the count of tasks assigned to a specific project. 74 | * 75 | * @return Collection 76 | */ 77 | public static function getAllForFormat(): \Illuminate\Support\Collection 78 | { 79 | return Task::all()->sortBy('created_at', 0, true)->slice(0, 5); 80 | } 81 | 82 | /** 83 | * Format tasks for display. 84 | * 85 | * @return array 86 | */ 87 | public static function formatTasks(): array 88 | { 89 | return Task::get()->map(function ($task) { 90 | $nameTask = Str::limit($task->name, 70); 91 | return [ 92 | 'id' => $task->id, 93 | 'name' => $nameTask, 94 | 'duration' => $task->duration, 95 | 'created_at' => $task->created_at, 96 | ]; 97 | })->toArray(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /database/seeders/SettingsSeeder.php: -------------------------------------------------------------------------------- 1 | insert( 18 | [ 19 | 'key' => 'pagination_size', 20 | 'value' => 5, 21 | 'description' => 'set pagination size', 22 | 'created_at' => now(), 23 | ] 24 | ); 25 | 26 | //currency 27 | DB::table('settings')->insert( 28 | [ 29 | 'key' => 'currency', 30 | 'value' => 'EUR', 31 | 'description' => 'set currency type', 32 | 'created_at' => now(), 33 | ] 34 | ); 35 | 36 | //priority_size 37 | DB::table('settings')->insert( 38 | [ 39 | 'key' => 'priority_size', 40 | 'value' => 3, 41 | 'description' => 'set priority size', 42 | 'created_at' => now(), 43 | ] 44 | ); 45 | 46 | //invoice_tax 47 | DB::table('settings')->insert( 48 | [ 49 | 'key' => 'invoice_tax', 50 | 'value' => 3, 51 | 'description' => 'set invoice tax size', 52 | 'created_at' => now(), 53 | ] 54 | ); 55 | 56 | //invoice_tax 57 | DB::table('settings')->insert( 58 | [ 59 | 'key' => 'invoice_tax', 60 | 'value' => 3, 61 | 'description' => 'set invoice tax size', 62 | 'created_at' => now(), 63 | ] 64 | ); 65 | 66 | //loading_circle 67 | DB::table('settings')->insert( 68 | [ 69 | 'key' => 'loading_circle', 70 | 'value' => 1, 71 | 'description' => 'set loading circle', 72 | 'created_at' => now(), 73 | ] 74 | ); 75 | 76 | // last deploy time 77 | DB::table('settings')->insert( 78 | [ 79 | 'key' => 'last_deploy_time', 80 | 'value' => now(), 81 | 'description' => 'set last deploy time', 82 | 'is_visible' => false, 83 | 'created_at' => now(), 84 | ] 85 | ); 86 | 87 | // last deploy version 88 | DB::table('settings')->insert( 89 | [ 90 | 'key' => 'last_deploy_version', 91 | 'value' => '1.0.0', 92 | 'description' => 'set last deploy version', 93 | 'is_visible' => false, 94 | 'created_at' => now(), 95 | ] 96 | ); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /resources/views/crm/auth/passwords/reset.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @include('layouts.head', ['title' => 'Password reset']) 4 | 5 | 6 |
7 | @include('layouts.sidebar') 8 | 9 |
10 | @include('layouts.header') 11 | 12 |
13 |
14 | @include('layouts.flash-messages') 15 |
16 | 17 |
18 |
19 |

Password reset

20 |
21 |
22 | 23 |
24 |
25 |
26 | @csrf 27 |
28 |
29 | @include('layouts.components.forms.input', [ 30 | 'name' => 'Old password', 31 | 'inputId' => 'old-password', 32 | 'inputName' => 'old_password', 33 | 'inputType' => 'password', 34 | 'inputRequired' => true 35 | ]) 36 |
37 | 38 |
39 | @include('layouts.components.forms.input', [ 40 | 'name' => 'New password', 41 | 'inputId' => 'new-password', 42 | 'inputName' => 'new_password', 43 | 'inputType' => 'password', 44 | 'inputRequired' => true 45 | ]) 46 | 47 | @include('layouts.components.forms.input', [ 48 | 'name' => 'Repeat new password', 49 | 'inputId' => 'confirm-password', 50 | 'inputName' => 'confirm_password', 51 | 'inputType' => 'password', 52 | 'inputRequired' => true 53 | ]) 54 |
55 |
56 | 57 |
58 | 59 |
60 |
61 |
62 |
63 |
64 | 65 | @include('layouts.footer') 66 |
67 |
68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /resources/views/layouts/flash-messages.blade.php: -------------------------------------------------------------------------------- 1 | @if(session()->has('message_error')) 2 | 11 | @endif 12 | 13 | @if(session()->has('message_success')) 14 | 23 | @endif 24 | 25 | @if ($errors->any()) 26 | 40 | @endif 41 | 42 | 57 | -------------------------------------------------------------------------------- /app/Services/GraphDataService.php: -------------------------------------------------------------------------------- 1 | "Added tasks", 23 | 'backgroundColor' => "rgba(38, 185, 154, 0.31)", 24 | 'borderColor' => "rgba(38, 185, 154, 0.7)", 25 | "pointBorderColor" => "rgba(38, 185, 154, 0.7)", 26 | "pointBackgroundColor" => "rgba(38, 185, 154, 0.7)", 27 | "pointHoverBackgroundColor" => "#fff", 28 | "pointHoverBorderColor" => "rgba(220,220,220,1)", 29 | 'data' => $cash->loadTaskEveryMonth(false) 30 | ], 31 | [ 32 | "label" => "Completed tasks", 33 | 'backgroundColor' => "rgba(38, 80, 186, 0.55)", 34 | 'borderColor' => "rgba(38, 80, 186, 1)", 35 | "pointBorderColor" => "rgba(38, 185, 154, 0.7)", 36 | "pointBackgroundColor" => "rgba(38, 185, 154, 0.7)", 37 | "pointHoverBackgroundColor" => "#fff", 38 | "pointHoverBorderColor" => "rgba(220,220,220,1)", 39 | 'data' => $cash->loadTaskEveryMonth(true) 40 | ] 41 | ]; 42 | 43 | return app()->chartjs 44 | ->name('taskGraphData') 45 | ->type('line') 46 | ->size(['width' => $this->width, 'height' => $this->height]) 47 | ->labels($labels) 48 | ->datasets($datasets) 49 | ->options([]); 50 | } 51 | 52 | 53 | /** 54 | * @return mixed 55 | */ 56 | public function itemsCountGraphData(): mixed 57 | { 58 | $data = [ 59 | 'Products' => ProductQueries::countAll(), 60 | 'Sales' => SaleQueries::countAll(), 61 | 'Finances' => FinanceQueries::countAll(), 62 | 'Deal' => DealQueries::countAll(), 63 | ]; 64 | 65 | $colors = [ 66 | 'Products' => ['rgba(227, 67, 51, 1)', 'rgba(54, 162, 235, 0.2)'], 67 | 'Sales' => ['rgba(228, 115, 45, 1)', 'rgba(54, 162, 235, 0.3)'], 68 | 'Finances' => ['rgba(249, 195, 100, 1)', 'rgba(54, 162, 235, 0.3)'], 69 | 'Deal' => ['rgba(92, 141, 93, 1)', 'rgba(54, 162, 235, 0.3)'], 70 | ]; 71 | 72 | $datasets = []; 73 | 74 | foreach ($data as $label => $count) { 75 | $datasets[] = [ 76 | 'label' => $label, 77 | 'backgroundColor' => $colors[$label], 78 | 'data' => [$count], 79 | ]; 80 | } 81 | 82 | return app()->chartjs 83 | ->name('cashTurnoverGraphData') 84 | ->type('bar') 85 | ->size(['width' => $this->width, 'height' => $this->height]) 86 | ->datasets($datasets) 87 | ->options([]); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /app/Http/Controllers/CRM/AuthController.php: -------------------------------------------------------------------------------- 1 | attempt($request->validated())) { 39 | return redirect()->to('/'); 40 | } else { 41 | return redirect()->back()->with('message_error', 'Wrong email or password!'); 42 | } 43 | } 44 | 45 | /** 46 | * Logout the admin from the system. 47 | * 48 | * @return \Illuminate\Http\RedirectResponse 49 | */ 50 | public function logout(): \Illuminate\Http\RedirectResponse 51 | { 52 | // Logout from system 53 | auth()->logout(); 54 | 55 | // Redirect to login page 56 | return redirect()->to('login')->with('message_success', 'You have been logged out from system.'); 57 | } 58 | 59 | /** 60 | * Render the view for changing the password. 61 | * 62 | * @return \Illuminate\View\View 63 | */ 64 | public function renderChangePasswordView(): \Illuminate\View\View 65 | { 66 | // Render the change password view. 67 | return view('crm.auth.passwords.reset'); 68 | } 69 | 70 | /** 71 | * Process the password change request. 72 | * 73 | * @param ChangePasswordRequest $request 74 | * @return \Illuminate\Http\RedirectResponse 75 | */ 76 | public function processChangePassword(ChangePasswordRequest $request): \Illuminate\Http\RedirectResponse 77 | { 78 | // Get validated data. 79 | $validatedData = $request->validated(); 80 | 81 | // Check if old password is correct. 82 | if (!Hash::check($validatedData['old_password'], auth()->user()->password)) { 83 | return redirect()->to('password/reset')->with('message_danger', 'Old password is incorrect.'); 84 | } 85 | 86 | // Check if new password and confirm password match. 87 | if ($validatedData['new_password'] !== $validatedData['confirm_password']) { 88 | return redirect()->to('password/reset')->with('message_danger', 'New password and confirm password do not match.'); 89 | } 90 | 91 | // Dispatch job to change password. 92 | $this->dispatchSync(new ChangePasswordJob($validatedData, auth()->user())); 93 | 94 | // Redirect to change password page. 95 | return redirect()->to('password/reset')->with('message_success', 'Your password has been changed.'); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at . All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /resources/views/crm/products/create.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @include('layouts.head', ['title' => 'Add new product']) 4 | 5 | 6 |
7 | @include('layouts.sidebar') 8 | 9 |
10 | @include('layouts.header') 11 | 12 |
13 |
14 | @include('layouts.flash-messages') 15 |
16 | 17 |
18 |
19 |

Add new product

20 | 21 | 24 | 25 |
26 |
27 | 28 |
29 |
30 |
31 | @csrf 32 |
33 |
34 | @include('layouts.components.forms.input', [ 35 | 'name' => 'Name', 36 | 'inputId' => 'name', 37 | 'inputName' => 'name', 38 | 'inputType' => 'text', 39 | 'inputRequired' => true 40 | ]) 41 | 42 | @include('layouts.components.forms.input', [ 43 | 'name' => 'Category', 44 | 'inputId' => 'category', 45 | 'inputName' => 'category', 46 | 'inputType' => 'text', 47 | 'inputRequired' => true 48 | ]) 49 |
50 | 51 |
52 | @include('layouts.components.forms.input', [ 53 | 'name' => 'Count', 54 | 'inputId' => 'count', 55 | 'inputName' => 'count', 56 | 'inputType' => 'number', 57 | 'inputRequired' => true 58 | ]) 59 | 60 | @include('layouts.components.forms.input', [ 61 | 'name' => 'Price', 62 | 'inputId' => 'price', 63 | 'inputName' => 'price', 64 | 'inputType' => 'number', 65 | 'inputRequired' => true 66 | ]) 67 |
68 |
69 | 70 |
71 | 72 |
73 |
74 |
75 |
76 | 77 |
78 | 79 | @include('layouts.footer') 80 |
81 |
82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_STORE', 'database'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | | Supported drivers: "array", "database", "file", "memcached", 30 | | "redis", "dynamodb", "octane", "null" 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'array' => [ 37 | 'driver' => 'array', 38 | 'serialize' => false, 39 | ], 40 | 41 | 'database' => [ 42 | 'driver' => 'database', 43 | 'connection' => env('DB_CACHE_CONNECTION'), 44 | 'table' => env('DB_CACHE_TABLE', 'cache'), 45 | 'lock_connection' => env('DB_CACHE_LOCK_CONNECTION'), 46 | 'lock_table' => env('DB_CACHE_LOCK_TABLE'), 47 | ], 48 | 49 | 'file' => [ 50 | 'driver' => 'file', 51 | 'path' => storage_path('framework/cache/data'), 52 | 'lock_path' => storage_path('framework/cache/data'), 53 | ], 54 | 55 | 'memcached' => [ 56 | 'driver' => 'memcached', 57 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 58 | 'sasl' => [ 59 | env('MEMCACHED_USERNAME'), 60 | env('MEMCACHED_PASSWORD'), 61 | ], 62 | 'options' => [ 63 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 64 | ], 65 | 'servers' => [ 66 | [ 67 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 68 | 'port' => env('MEMCACHED_PORT', 11211), 69 | 'weight' => 100, 70 | ], 71 | ], 72 | ], 73 | 74 | 'redis' => [ 75 | 'driver' => 'redis', 76 | 'connection' => env('REDIS_CACHE_CONNECTION', 'cache'), 77 | 'lock_connection' => env('REDIS_CACHE_LOCK_CONNECTION', 'default'), 78 | ], 79 | 80 | 'dynamodb' => [ 81 | 'driver' => 'dynamodb', 82 | 'key' => env('AWS_ACCESS_KEY_ID'), 83 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 84 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 85 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 86 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 87 | ], 88 | 89 | 'octane' => [ 90 | 'driver' => 'octane', 91 | ], 92 | 93 | ], 94 | 95 | /* 96 | |-------------------------------------------------------------------------- 97 | | Cache Key Prefix 98 | |-------------------------------------------------------------------------- 99 | | 100 | | When utilizing the APC, database, memcached, Redis, and DynamoDB cache 101 | | stores, there might be other applications using the same cache. For 102 | | that reason, you may prefix every cache key to avoid collisions. 103 | | 104 | */ 105 | 106 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'), 107 | 108 | ]; 109 | -------------------------------------------------------------------------------- /app/Services/CalculateCashService.php: -------------------------------------------------------------------------------- 1 | price * $product->count; 23 | }); 24 | 25 | $salesSum = Sale::sum(function ($sale) { 26 | return $sale->price * $sale->quantity; 27 | }); 28 | 29 | $financesSum = Finance::sum('net'); 30 | 31 | $officialSum = $productSum + $salesSum + $financesSum; 32 | 33 | return Money::{SettingQueries::getSettingValue('currency')}($officialSum); 34 | } 35 | 36 | /** 37 | * @return mixed 38 | */ 39 | public function loadCountTodayIncome(): mixed 40 | { 41 | $productSum = Product::whereDate('created_at', Carbon::today()) 42 | ->sum(function ($product) { 43 | return $product->price * $product->count; 44 | }); 45 | 46 | $salesSum = Sale::whereDate('created_at', Carbon::today()) 47 | ->sum(function ($sale) { 48 | return $sale->price * $sale->quantity; 49 | }); 50 | 51 | $financesSum = Finance::whereDate('created_at', Carbon::today())->sum('net'); 52 | 53 | $todayIncome = $productSum + $salesSum + $financesSum; 54 | 55 | return Money::{SettingQueries::getSettingValue('currency')}($todayIncome); 56 | } 57 | 58 | /** 59 | * @return mixed 60 | */ 61 | public function loadCountYesterdayIncome(): mixed 62 | { 63 | $productSum = Product::whereDate('created_at', Carbon::yesterday()) 64 | ->sum(function ($product) { 65 | return $product->price * $product->count; 66 | }); 67 | 68 | $salesSum = Sale::whereDate('created_at', Carbon::yesterday()) 69 | ->sum(function ($sale) { 70 | return $sale->price * $sale->quantity; 71 | }); 72 | 73 | $financesSum = Finance::whereDate('created_at', Carbon::yesterday())->sum('net'); 74 | 75 | $yesterdayIncome = $productSum + $salesSum + $financesSum; 76 | 77 | return Money::{SettingQueries::getSettingValue('currency')}($yesterdayIncome); 78 | } 79 | 80 | /** 81 | * @return int 82 | */ 83 | public function loadCountAllRowsInDb(): int 84 | { 85 | $counter = 0; 86 | $tables = DB::select('SHOW TABLES'); 87 | $databaseName = DB::connection()->getDatabaseName(); 88 | 89 | foreach ($tables as $table) { 90 | $tableName = $table->{'Tables_in_' . $databaseName}; 91 | $counter += DB::table($tableName)->count(); 92 | } 93 | 94 | return $counter; 95 | } 96 | 97 | public function loadTaskEveryMonth(bool $isCompleted): array 98 | { 99 | $dates = collect(); 100 | foreach (range(-6, 0) as $i) { 101 | $date = Carbon::now()->addDays($i)->format('Y-m-d'); 102 | $dates->put($date, 0); 103 | } 104 | 105 | $query = Task::where('created_at', '>=', $dates->keys()->first()) 106 | ->groupBy(DB::raw('DATE(created_at)')) 107 | ->orderBy('created_at'); 108 | 109 | if ($isCompleted) { 110 | $query->where('completed', 1); 111 | } 112 | 113 | $posts = $query->get([ 114 | DB::raw('DATE(created_at) as date'), 115 | DB::raw('COUNT(*) as "count"') 116 | ])->pluck('count', 'date'); 117 | 118 | // Merge posts data with the default zeroed dates 119 | $dates = $dates->merge($posts); 120 | 121 | return $dates->values()->toArray(); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'log'), 18 | 19 | /* 20 | |-------------------------------------------------------------------------- 21 | | Mailer Configurations 22 | |-------------------------------------------------------------------------- 23 | | 24 | | Here you may configure all of the mailers used by your application plus 25 | | their respective settings. Several examples have been configured for 26 | | you and you are free to add your own as your application requires. 27 | | 28 | | Laravel supports a variety of mail "transport" drivers that can be used 29 | | when delivering an email. You may specify which one you're using for 30 | | your mailers below. You may also add additional mailers if needed. 31 | | 32 | | Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2", 33 | | "postmark", "resend", "log", "array", 34 | | "failover", "roundrobin" 35 | | 36 | */ 37 | 38 | 'mailers' => [ 39 | 40 | 'smtp' => [ 41 | 'transport' => 'smtp', 42 | 'url' => env('MAIL_URL'), 43 | 'host' => env('MAIL_HOST', '127.0.0.1'), 44 | 'port' => env('MAIL_PORT', 2525), 45 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 46 | 'username' => env('MAIL_USERNAME'), 47 | 'password' => env('MAIL_PASSWORD'), 48 | 'timeout' => null, 49 | 'local_domain' => env('MAIL_EHLO_DOMAIN', parse_url(env('APP_URL', 'http://localhost'), PHP_URL_HOST)), 50 | ], 51 | 52 | 'ses' => [ 53 | 'transport' => 'ses', 54 | ], 55 | 56 | 'postmark' => [ 57 | 'transport' => 'postmark', 58 | // 'message_stream_id' => env('POSTMARK_MESSAGE_STREAM_ID'), 59 | // 'client' => [ 60 | // 'timeout' => 5, 61 | // ], 62 | ], 63 | 64 | 'resend' => [ 65 | 'transport' => 'resend', 66 | ], 67 | 68 | 'sendmail' => [ 69 | 'transport' => 'sendmail', 70 | 'path' => env('MAIL_SENDMAIL_PATH', '/usr/sbin/sendmail -bs -i'), 71 | ], 72 | 73 | 'log' => [ 74 | 'transport' => 'log', 75 | 'channel' => env('MAIL_LOG_CHANNEL'), 76 | ], 77 | 78 | 'array' => [ 79 | 'transport' => 'array', 80 | ], 81 | 82 | 'failover' => [ 83 | 'transport' => 'failover', 84 | 'mailers' => [ 85 | 'smtp', 86 | 'log', 87 | ], 88 | ], 89 | 90 | 'roundrobin' => [ 91 | 'transport' => 'roundrobin', 92 | 'mailers' => [ 93 | 'ses', 94 | 'postmark', 95 | ], 96 | ], 97 | 98 | ], 99 | 100 | /* 101 | |-------------------------------------------------------------------------- 102 | | Global "From" Address 103 | |-------------------------------------------------------------------------- 104 | | 105 | | You may wish for all emails sent by your application to be sent from 106 | | the same address. Here you may specify a name and address that is 107 | | used globally for all emails that are sent by your application. 108 | | 109 | */ 110 | 111 | 'from' => [ 112 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 113 | 'name' => env('MAIL_FROM_NAME', 'Example'), 114 | ], 115 | 116 | ]; 117 | -------------------------------------------------------------------------------- /resources/views/crm/sales/show.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | @include('layouts.head', ['title' => 'Show sale']) 4 | 5 | 6 |
7 | @include('layouts.sidebar') 8 | 9 |
10 | @include('layouts.header') 11 | 12 |
13 |
14 | @include('layouts.flash-messages') 15 |
16 | 17 |
18 | 30 |
31 | 32 |
33 |
34 | 41 | 42 |
43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
Name{{ $sale->name }}
Quantity{{ $sale->quantity }}
Date of payment{{ $sale->date_of_payment }}
Assigned Product 65 | {{ $sale->product->name }} 66 |
Status{{ $sale->is_active ? 'Active' : 'Deactivate' }}
75 |
76 |
77 |
78 |
79 |
80 | 81 | @include('layouts.footer') 82 |
83 |
84 | 85 | 86 | 87 | 88 | --------------------------------------------------------------------------------