├── public ├── favicon.ico ├── assets │ ├── .gitignore │ ├── css │ │ ├── .gitignore │ │ └── plugins │ │ │ ├── morris.css │ │ │ └── metisMenu │ │ │ └── metisMenu.min.css │ ├── js │ │ ├── .gitignore │ │ └── sb-admin-2.js │ ├── imgs │ │ ├── .gitignore │ │ ├── default-logo.png │ │ ├── icon_user_1.png │ │ └── icon_user_2.png │ └── fonts │ │ ├── FontAwesome.otf │ │ ├── fontawesome-webfont.eot │ │ ├── fontawesome-webfont.ttf │ │ ├── fontawesome-webfont.woff │ │ └── fontawesome-webfont.woff2 ├── robots.txt ├── mix-manifest.json ├── screenshots │ ├── pmo-testing-01.jpg │ ├── pmo-dashboard-01.jpg │ ├── pmo-job-tasks-01.jpg │ ├── pmo-project-jobs-01.jpg │ ├── pmo-install-free-pmo.jpg │ ├── pmo-project-detail-01.jpg │ └── pmo-yearly-report-01.jpg ├── .htaccess └── web.config ├── database ├── seeds │ ├── .gitkeep │ └── DatabaseSeeder.php ├── migrations │ ├── .gitkeep │ ├── 2015_07_14_131409_create_site_options_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ ├── 2017_11_14_061927_create_user_roles_table.php │ ├── 2017_11_01_185745_create_vendors_table.php │ ├── 2018_08_04_110400_create_comments_table.php │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2016_07_09_142833_create_tasks_table.php │ ├── 2018_10_30_215937_create_bank_accounts_table.php │ ├── 2017_08_03_235706_create_files_table.php │ ├── 2016_11_25_145359_create_user_events_table.php │ ├── 2019_03_03_210017_create_issues_table.php │ ├── 2017_10_26_134455_create_customers_table.php │ └── 2016_11_15_151228_create_payments_table.php ├── .gitignore └── factories │ ├── VendorFactory.php │ ├── CustomerFactory.php │ ├── BankAccountFactory.php │ ├── CommentFactory.php │ ├── IssueFactory.php │ ├── InvoiceFactory.php │ ├── ProjectFactory.php │ └── SubscriptionFactory.php ├── README.md ├── bootstrap ├── cache │ └── .gitignore └── autoload.php ├── storage ├── debugbar │ └── .gitignore ├── logs │ └── .gitignore ├── framework │ ├── cache │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ ├── views │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ └── .gitignore └── app │ ├── .gitignore │ ├── public │ └── .gitignore │ └── sample-image.png ├── .gitattributes ├── .styleci.yml ├── resources ├── views │ ├── auth │ │ ├── emails │ │ │ └── password.blade.php │ │ ├── login.blade.php │ │ └── passwords │ │ │ ├── email.blade.php │ │ │ ├── reset.blade.php │ │ │ └── change.blade.php │ ├── users │ │ ├── activities │ │ │ ├── activity_list_item.blade.php │ │ │ ├── jobs │ │ │ │ ├── job_created.blade.php │ │ │ │ ├── task_deleted.blade.php │ │ │ │ └── job_updated.blade.php │ │ │ ├── tasks │ │ │ │ ├── task_created.blade.php │ │ │ │ └── task_updated.blade.php │ │ │ └── projects │ │ │ │ ├── project_created.blade.php │ │ │ │ ├── job_deleted.blade.php │ │ │ │ └── project_updated.blade.php │ │ ├── partials │ │ │ ├── breadcrumb.blade.php │ │ │ └── nav-tabs.blade.php │ │ └── profile │ │ │ ├── edit.blade.php │ │ │ └── show.blade.php │ ├── subscriptions │ │ ├── partials │ │ │ ├── breadcrumb.blade.php │ │ │ ├── delete.blade.php │ │ │ └── subscription-show.blade.php │ │ └── show.blade.php │ ├── jobs │ │ ├── partials │ │ │ ├── breadcrumb.blade.php │ │ │ ├── nav-tabs.blade.php │ │ │ ├── job-show.blade.php │ │ │ └── job-dates.blade.php │ │ └── delete.blade.php │ ├── payments │ │ ├── partials │ │ │ ├── breadcrumb.blade.php │ │ │ └── payment-show.blade.php │ │ ├── delete.blade.php │ │ └── show.blade.php │ ├── projects │ │ ├── partials │ │ │ └── breadcrumb.blade.php │ │ ├── activities │ │ │ └── index.blade.php │ │ ├── delete.blade.php │ │ └── show.blade.php │ ├── layouts │ │ ├── user.blade.php │ │ ├── partials │ │ │ ├── footer.blade.php │ │ │ ├── noty.blade.php │ │ │ └── lang-switcher.blade.php │ │ ├── project.blade.php │ │ ├── print.blade.php │ │ ├── customer.blade.php │ │ ├── job.blade.php │ │ ├── dashboard.blade.php │ │ └── guest.blade.php │ ├── view-components │ │ ├── sidebar-project-list-links.blade.php │ │ └── dashboard-panel.blade.php │ ├── invoices │ │ └── partials │ │ │ └── detail.blade.php │ ├── invoice-drafts │ │ └── partials │ │ │ └── invoice-draft-tabs.blade.php │ ├── customers │ │ └── partials │ │ │ └── nav-tabs.blade.php │ ├── pages │ │ └── partials │ │ │ └── dashboard-nav-tabs.blade.php │ └── errors │ │ └── 503.blade.php ├── lang │ ├── en │ │ ├── nav_menu.php │ │ ├── contact.php │ │ ├── lang.php │ │ ├── event.php │ │ ├── address.php │ │ ├── app_install.php │ │ ├── dashboard.php │ │ ├── option.php │ │ ├── time.php │ │ ├── pagination.php │ │ ├── comment.php │ │ ├── agency.php │ │ ├── activity.php │ │ ├── passwords.php │ │ ├── task.php │ │ ├── report.php │ │ ├── file.php │ │ ├── vendor.php │ │ └── bank_account.php │ ├── id │ │ ├── nav_menu.php │ │ ├── contact.php │ │ ├── lang.php │ │ ├── event.php │ │ ├── address.php │ │ ├── app_install.php │ │ ├── dashboard.php │ │ ├── option.php │ │ ├── time.php │ │ ├── pagination.php │ │ ├── comment.php │ │ ├── agency.php │ │ ├── activity.php │ │ ├── passwords.php │ │ ├── report.php │ │ ├── file.php │ │ ├── vendor.php │ │ └── task.php │ └── de │ │ ├── nav_menu.php │ │ ├── contact.php │ │ ├── lang.php │ │ ├── event.php │ │ ├── address.php │ │ ├── app_install.php │ │ ├── option.php │ │ ├── dashboard.php │ │ ├── time.php │ │ ├── pagination.php │ │ ├── comment.php │ │ ├── activity.php │ │ ├── agency.php │ │ ├── passwords.php │ │ ├── report.php │ │ ├── task.php │ │ └── file.php └── assets │ └── js │ └── app.js ├── SECURITY.md ├── routes ├── api │ └── projects.php ├── web │ ├── calendar.php │ ├── pages.php │ ├── payments.php │ ├── users.php │ ├── references.php │ └── reports.php ├── channels.php ├── console.php └── api.php ├── app ├── Events │ ├── Jobs │ │ ├── Created.php │ │ ├── Deleted.php │ │ └── Updated.php │ ├── Tasks │ │ ├── Created.php │ │ ├── Deleted.php │ │ └── Updated.php │ └── Projects │ │ ├── Created.php │ │ └── Updated.php ├── Exceptions │ └── ReferenceKeyNotFoundException.php ├── Http │ ├── Middleware │ │ ├── EncryptCookies.php │ │ ├── VerifyCsrfToken.php │ │ ├── TrimStrings.php │ │ ├── Lang.php │ │ ├── TrustProxies.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── Authenticate.php │ │ ├── GlobalViewVariables.php │ │ └── Role.php │ ├── Controllers │ │ ├── Api │ │ │ ├── VendorController.php │ │ │ ├── CustomerController.php │ │ │ └── ProjectsController.php │ │ ├── Users │ │ │ ├── JobsController.php │ │ │ ├── CalendarController.php │ │ │ └── ProjectsController.php │ │ ├── PagesController.php │ │ ├── Customers │ │ │ ├── ProjectsController.php │ │ │ ├── InvoicesController.php │ │ │ ├── SubscriptionsController.php │ │ │ └── PaymentsController.php │ │ ├── Projects │ │ │ ├── InvoicesController.php │ │ │ └── ActivityController.php │ │ ├── Issues │ │ │ └── OptionController.php │ │ ├── References │ │ │ └── SiteOptionsController.php │ │ ├── Auth │ │ │ └── ForgotPasswordController.php │ │ ├── Invoices │ │ │ └── DuplicationController.php │ │ └── Reports │ │ │ └── LogFileController.php │ └── Requests │ │ ├── Request.php │ │ ├── Payments │ │ ├── DeleteRequest.php │ │ └── UpdateRequest.php │ │ ├── Tasks │ │ ├── DeleteRequest.php │ │ ├── CreateRequest.php │ │ └── UpdateRequest.php │ │ ├── Jobs │ │ ├── DeleteRequest.php │ │ ├── UpdateRequest.php │ │ └── CreateRequest.php │ │ ├── Accounts │ │ └── RegisterRequest.php │ │ └── Partners │ │ ├── CustomerCreateRequest.php │ │ └── CustomerUpdateRequest.php ├── Entities │ ├── Users │ │ ├── Activity.php │ │ └── UserRole.php │ ├── Options │ │ └── Option.php │ ├── Projects │ │ ├── Comment.php │ │ ├── ProjectPresenter.php │ │ ├── JobPresenter.php │ │ ├── Task.php │ │ ├── Priority.php │ │ ├── IssueStatus.php │ │ └── File.php │ ├── Invoices │ │ └── BankAccount.php │ ├── Payments │ │ ├── PaymentPresenter.php │ │ ├── Type.php │ │ └── Payment.php │ ├── Partners │ │ └── Vendor.php │ └── BaseRepository.php ├── Policies │ ├── EventPolicy.php │ └── Projects │ │ └── IssuePolicy.php ├── Listeners │ ├── Jobs │ │ ├── LogJobCreationActivity.php │ │ └── LogJobTaskDeletionActivity.php │ ├── Projects │ │ ├── LogProjectCreationActivity.php │ │ └── LogProjectJobDeletionActivity.php │ └── Tasks │ │ └── LogTaskCreationActivity.php ├── Console │ ├── Commands │ │ └── Inspire.php │ └── Kernel.php └── Providers │ └── AppServiceProvider.php ├── .gitignore ├── .travis.yml ├── server.php ├── tests ├── CreatesApplication.php ├── Unit │ ├── Models │ │ ├── BankAccountTest.php │ │ └── CommentTest.php │ ├── Policies │ │ └── IssuePolicyTest.php │ └── Helpers │ │ └── MoneyFormatTest.php ├── Feature │ └── Api │ │ ├── ApiManageProjectsTest.php │ │ ├── Projects │ │ ├── ReorderTaskListTest.php │ │ └── ReorderJobListTest.php │ │ └── FetchPartnerListTest.php └── TestCase.php ├── webpack.mix.js ├── .env.example ├── package.json ├── LICENSE ├── config ├── compile.php ├── services.php ├── view.php └── simple-crud.php └── phpunit.xml /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/seeds/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/css/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/assets/js/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | project management with laravel 2 | -------------------------------------------------------------------------------- /bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/debugbar/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | !sample-image.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.css linguist-vendored 3 | *.less linguist-vendored 4 | -------------------------------------------------------------------------------- /.styleci.yml: -------------------------------------------------------------------------------- 1 | preset: laravel 2 | 3 | disabled: 4 | - not_operator_with_successor_space -------------------------------------------------------------------------------- /storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | assets/imgs/* 3 | !assets/imgs/icon_user_1.png 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /public/assets/imgs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !default-logo.png 4 | !icon_user_1.png 5 | !icon_user_2.png 6 | -------------------------------------------------------------------------------- /resources/views/auth/emails/password.blade.php: -------------------------------------------------------------------------------- 1 | Click here to reset your password: {{ route('auth.reset', $token) }} -------------------------------------------------------------------------------- /public/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/assets/js/app.js": "/assets/js/app.js", 3 | "/assets/css/app.css": "/assets/css/app.css" 4 | } -------------------------------------------------------------------------------- /storage/app/sample-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/storage/app/sample-image.png -------------------------------------------------------------------------------- /public/assets/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /public/assets/imgs/default-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/imgs/default-logo.png -------------------------------------------------------------------------------- /public/assets/imgs/icon_user_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/imgs/icon_user_1.png -------------------------------------------------------------------------------- /public/assets/imgs/icon_user_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/imgs/icon_user_2.png -------------------------------------------------------------------------------- /public/screenshots/pmo-testing-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-testing-01.jpg -------------------------------------------------------------------------------- /storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | config.php 2 | routes.php 3 | compiled.php 4 | services.json 5 | events.scanned.php 6 | routes.scanned.php 7 | down 8 | -------------------------------------------------------------------------------- /public/screenshots/pmo-dashboard-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-dashboard-01.jpg -------------------------------------------------------------------------------- /public/screenshots/pmo-job-tasks-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-job-tasks-01.jpg -------------------------------------------------------------------------------- /public/screenshots/pmo-project-jobs-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-project-jobs-01.jpg -------------------------------------------------------------------------------- /public/assets/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /public/assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /public/assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /public/assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /public/screenshots/pmo-install-free-pmo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-install-free-pmo.jpg -------------------------------------------------------------------------------- /public/screenshots/pmo-project-detail-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-project-detail-01.jpg -------------------------------------------------------------------------------- /public/screenshots/pmo-yearly-report-01.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sailingdev/project-management-laravel/HEAD/public/screenshots/pmo-yearly-report-01.jpg -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting a Vulnerability 2 | 3 | If you discover any security related issues, please email nafiesl@gmail.com instead of using the issue tracker. 4 | -------------------------------------------------------------------------------- /resources/views/users/activities/activity_list_item.blade.php: -------------------------------------------------------------------------------- 1 |
  • 2 | {{ $time }} 3 | {{ $body }} 4 |
  • 5 | -------------------------------------------------------------------------------- /routes/api/projects.php: -------------------------------------------------------------------------------- 1 | 'projects.jobs', 'uses' => 'ProjectsController@jobs']); 5 | -------------------------------------------------------------------------------- /resources/lang/en/nav_menu.php: -------------------------------------------------------------------------------- 1 | 'Dashboard', 5 | 'agency' => 'Agency Profile', 6 | 'calendar' => 'Calendar', 7 | 'nav' => 'Backup/Restore DB', 8 | ]; 9 | -------------------------------------------------------------------------------- /resources/lang/id/nav_menu.php: -------------------------------------------------------------------------------- 1 | 'Dashboard', 5 | 'agency' => 'Profil Agensi', 6 | 'calendar' => 'Kalender', 7 | 'nav' => 'Backup/Restore DB', 8 | ]; 9 | -------------------------------------------------------------------------------- /resources/lang/de/nav_menu.php: -------------------------------------------------------------------------------- 1 | 'Dashboard', 5 | 'agency' => 'Agenturprofil', 6 | 'calendar' => 'Kalender', 7 | 'nav' => 'DB Backup/Wiederherstellung', 8 | ]; 9 | -------------------------------------------------------------------------------- /database/factories/VendorFactory.php: -------------------------------------------------------------------------------- 1 | define(Vendor::class, function (Faker $faker) { 7 | return [ 8 | 'name' => $faker->company, 9 | ]; 10 | }); 11 | -------------------------------------------------------------------------------- /resources/lang/de/contact.php: -------------------------------------------------------------------------------- 1 | 'Kontakt', 5 | 'phone' => 'Telefon', 6 | 'phone_abb' => 'Tel.', 7 | 'cellphone' => 'Handy', 8 | 'email' => 'E-Mail', 9 | 'website' => 'Webseite', 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/lang/en/contact.php: -------------------------------------------------------------------------------- 1 | 'Contact', 5 | 'phone' => 'Phone', 6 | 'phone_abb' => 'Phone', 7 | 'cellphone' => 'Cell phone', 8 | 'email' => 'Email', 9 | 'website' => 'Website', 10 | ]; 11 | -------------------------------------------------------------------------------- /routes/web/calendar.php: -------------------------------------------------------------------------------- 1 | ['web', 'auth'], 'namespace' => 'Users'], function () { 4 | /* 5 | * User Calendar Route 6 | */ 7 | Route::get('my-calendar', 'CalendarController@index')->name('users.calendar'); 8 | }); 9 | -------------------------------------------------------------------------------- /resources/lang/en/lang.php: -------------------------------------------------------------------------------- 1 | 'Language', 5 | 'switch_tooltip' => 'Switch language to :lang', 6 | 'en' => 'English', 7 | 'id' => 'Bahasa', 8 | 'de' => 'German', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/lang/id/contact.php: -------------------------------------------------------------------------------- 1 | 'Kontak', 5 | 'phone' => 'Telepon', 6 | 'phone_abb' => 'Telp.', 7 | 'cellphone' => 'Telepon Selular', 8 | 'email' => 'Email', 9 | 'website' => 'Website', 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/lang/id/lang.php: -------------------------------------------------------------------------------- 1 | 'Bahasa', 5 | 'switch_tooltip' => 'Ubah bahasa ke :lang', 6 | 'en' => 'Inggris', 7 | 'id' => 'Indonesia', 8 | 'de' => 'Jerman', 9 | ]; 10 | -------------------------------------------------------------------------------- /app/Events/Jobs/Created.php: -------------------------------------------------------------------------------- 1 | job = $job; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Events/Jobs/Deleted.php: -------------------------------------------------------------------------------- 1 | job = $job; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Events/Jobs/Updated.php: -------------------------------------------------------------------------------- 1 | job = $job; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /database/factories/CustomerFactory.php: -------------------------------------------------------------------------------- 1 | define(Customer::class, function (Faker $faker) { 7 | return [ 8 | 'name' => $faker->company, 9 | ]; 10 | }); 11 | -------------------------------------------------------------------------------- /resources/views/users/partials/breadcrumb.blade.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/lang/de/lang.php: -------------------------------------------------------------------------------- 1 | 'Sprache', 5 | 'switch_tooltip' => 'Sprache wechseln zu :lang', 6 | 'en' => 'Englisch', 7 | 'id' => 'Indonesisch', 8 | 'de' => 'Deutsch', 9 | ]; 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | /node_modules 3 | /public/hot 4 | /public/storage 5 | Homestead.yaml 6 | Homestead.json 7 | /storage/*.key 8 | /.vagrant 9 | npm-debug.log 10 | .env 11 | /.idea/ 12 | .phpunit.result.cache 13 | .php_cs.cache 14 | .env.backup 15 | yarn-error.log 16 | /ftpsync.settings -------------------------------------------------------------------------------- /app/Events/Tasks/Created.php: -------------------------------------------------------------------------------- 1 | task = $task; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Events/Tasks/Deleted.php: -------------------------------------------------------------------------------- 1 | task = $task; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Events/Tasks/Updated.php: -------------------------------------------------------------------------------- 1 | task = $task; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /resources/lang/de/event.php: -------------------------------------------------------------------------------- 1 | 'Event created.', 5 | 'edit' => 'Edit Events', 6 | 'updated' => 'Event updated.', 7 | 'deleted' => 'Event deleted.', 8 | 'rescheduled' => 'Event has been rescheduled.', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/lang/en/event.php: -------------------------------------------------------------------------------- 1 | 'Event created.', 5 | 'edit' => 'Edit Events', 6 | 'updated' => 'Event updated.', 7 | 'deleted' => 'Event deleted.', 8 | 'rescheduled' => 'Event has been rescheduled.', 9 | ]; 10 | -------------------------------------------------------------------------------- /app/Exceptions/ReferenceKeyNotFoundException.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class ReferenceKeyNotFoundException extends \RuntimeException 11 | { 12 | } 13 | -------------------------------------------------------------------------------- /resources/assets/js/app.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * First we will load all of this project's JavaScript dependencies which 4 | * includes Vue and other libraries. It is a great starting point when 5 | * building robust, powerful web applications using Vue and Laravel. 6 | */ 7 | 8 | require('./bootstrap'); 9 | -------------------------------------------------------------------------------- /database/seeds/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | project = $project; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/Events/Projects/Updated.php: -------------------------------------------------------------------------------- 1 | project = $project; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /resources/lang/id/event.php: -------------------------------------------------------------------------------- 1 | 'Event berhasil diinput.', 5 | 'edit' => 'Edit Event', 6 | 'updated' => 'Event berhasil diupdate.', 7 | 'deleted' => 'Event berhasil dihapus.', 8 | 'rescheduled' => 'Jadwal event berhasil diubah.', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/views/subscriptions/partials/breadcrumb.blade.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/views/jobs/partials/breadcrumb.blade.php: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /routes/web/pages.php: -------------------------------------------------------------------------------- 1 | route('home'); 8 | }); 9 | Route::get('about', ['as' => 'about', 'uses' => 'PagesController@about', 'middleware' => ['web']]); 10 | Route::get('home', ['as' => 'home', 'uses' => 'PagesController@home', 'middleware' => ['web', 'auth']]); 11 | -------------------------------------------------------------------------------- /resources/views/payments/partials/breadcrumb.blade.php: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /resources/views/projects/partials/breadcrumb.blade.php: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /resources/views/users/activities/jobs/job_created.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 7 | 'user' => $activity->user->name, 8 | 'name' => $activity->object->name, 9 | ]) !!} 10 | @endslot 11 | @endcomponent 12 | -------------------------------------------------------------------------------- /resources/views/users/activities/tasks/task_created.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 7 | 'user' => $activity->user->name, 8 | 'name' => $activity->object->name, 9 | ]) !!} 10 | @endslot 11 | @endcomponent 12 | -------------------------------------------------------------------------------- /app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | created_at }} 4 | @endslot 5 | @slot('body') 6 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 7 | 'user' => $activity->user->name, 8 | 'name' => $activity->object->name, 9 | ]) !!} 10 | @endslot 11 | @endcomponent 12 | -------------------------------------------------------------------------------- /app/Http/Middleware/VerifyCsrfToken.php: -------------------------------------------------------------------------------- 1 | 'Adresse', 5 | 'contact' => 'Kontakt', 6 | 'street' => 'Straße', 7 | 'rt' => 'RT', 8 | 'rw' => 'RW', 9 | 'village' => 'Ort', 10 | 'district' => 'Ortsteil', 11 | 'municipality' => 'Gemeinde', 12 | 'city' => 'Stadt', 13 | 'province' => 'Bundesland', 14 | ]; 15 | -------------------------------------------------------------------------------- /resources/lang/en/address.php: -------------------------------------------------------------------------------- 1 | 'Address', 5 | 'contact' => 'Contact', 6 | 'street' => 'Steet', 7 | 'rt' => 'RT', 8 | 'rw' => 'RW', 9 | 'village' => 'Village', 10 | 'district' => 'District', 11 | 'municipality' => 'Municipality', 12 | 'city' => 'City', 13 | 'province' => 'Province', 14 | ]; 15 | -------------------------------------------------------------------------------- /resources/views/layouts/user.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title') 4 | @yield('subtitle', trans('user.profile')) | {{ $user->name }} 5 | @endsection 6 | 7 | @section('content') 8 | @include('users.partials.breadcrumb') 9 |
    10 | @yield('action-buttons') 11 |
    12 | @include('users.partials.nav-tabs') 13 | @yield('content-user') 14 | @endsection 15 | -------------------------------------------------------------------------------- /database/factories/BankAccountFactory.php: -------------------------------------------------------------------------------- 1 | define(BankAccount::class, function (Faker $faker) { 8 | return [ 9 | 'name' => 'Bank '.strtoupper(Str::random(4)), 10 | 'number' => Str::random(10), 11 | 'account_name' => $faker->name, 12 | ]; 13 | }); 14 | -------------------------------------------------------------------------------- /resources/lang/id/address.php: -------------------------------------------------------------------------------- 1 | 'Alamat', 5 | 'contact' => 'Kontak', 6 | 'street' => 'Jalan', 7 | 'rt' => 'RT', 8 | 'rw' => 'RW', 9 | 'village' => 'Kelurahan/Desa', 10 | 'district' => 'Kecamatan', 11 | 'municipality' => 'Kota/Kab.', 12 | 'city' => 'Kota', 13 | 'province' => 'Propinsi', 14 | ]; 15 | -------------------------------------------------------------------------------- /routes/web/payments.php: -------------------------------------------------------------------------------- 1 | ['web', 'role:admin']], function () { 4 | /* 5 | * Payments Routes 6 | */ 7 | Route::get('payments/{payment}/pdf', ['as' => 'payments.pdf', 'uses' => 'PaymentsController@pdf']); 8 | Route::get('payments/{payment}/delete', ['as' => 'payments.delete', 'uses' => 'PaymentsController@delete']); 9 | Route::resource('payments', 'PaymentsController'); 10 | }); 11 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | orderBy('name') 14 | ->pluck('name', 'id'); 15 | 16 | return response()->json($vendors); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/lang/en/app_install.php: -------------------------------------------------------------------------------- 1 | 'Install '.config('app.name').'', 5 | 'agency_info_text' => 'Please fill form below to create your Agency.', 6 | 'admin_info_text' => 'Please fill form below to create an Administrator Account.', 7 | 'admin_name' => 'Administrator Name', 8 | 'admin_email' => 'Administrator Email', 9 | 'button' => 'Install Free PMO', 10 | ]; 11 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/CustomerController.php: -------------------------------------------------------------------------------- 1 | orderBy('name') 14 | ->pluck('name', 'id'); 15 | 16 | return response()->json($customers); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /resources/lang/id/app_install.php: -------------------------------------------------------------------------------- 1 | 'Install '.config('app.name').'', 5 | 'agency_info_text' => 'Silakan isi formulir di bawah ini untuk membuat Agensi.', 6 | 'admin_info_text' => 'Silakan isi formulir di bawah ini untuk membuat akun Administrator.', 7 | 'admin_name' => 'Nama Administrator', 8 | 'admin_email' => 'Email Administrator', 9 | 'button' => 'Install Free PMO', 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/views/jobs/partials/nav-tabs.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 12 |
    13 | -------------------------------------------------------------------------------- /resources/views/layouts/partials/footer.blade.php: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /routes/web/users.php: -------------------------------------------------------------------------------- 1 | ['web', 'role:admin'], 'namespace' => 'Users'], function () { 4 | /* 5 | * Users Routes 6 | */ 7 | Route::get('users/{user}/jobs', ['as' => 'users.jobs', 'uses' => 'JobsController@index']); 8 | Route::get('users/{user}/projects', ['as' => 'users.projects', 'uses' => 'ProjectsController@index']); 9 | Route::get('users/{user}/delete', ['as' => 'users.delete', 'uses' => 'UsersController@delete']); 10 | Route::resource('users', 'UsersController'); 11 | }); 12 | -------------------------------------------------------------------------------- /app/Http/Middleware/Lang.php: -------------------------------------------------------------------------------- 1 | user()) { 19 | app()->setLocale($request->user()->lang); 20 | } 21 | 22 | return $next($request); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/lang/de/app_install.php: -------------------------------------------------------------------------------- 1 | 'Install '.config('app.name').'', 5 | 'agency_info_text' => 'Bitte füllen Sie das nachfolgende Fomular aus, um Ihre Agentur anzulegen.', 6 | 'admin_info_text' => 'Bitte füllen Sie das nachfolgende Formular aus, um einen Administrator Account anzulegen.', 7 | 'admin_name' => 'Administrator Name', 8 | 'admin_email' => 'Administrator E-Mail', 9 | 'button' => 'installiere jetzt Free PMO', 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/lang/en/dashboard.php: -------------------------------------------------------------------------------- 1 | 'Project Status Stat', 5 | 'earnings_stats' => 'Earning Stat', 6 | 'upcoming_subscriptions_expiry' => 'Upcoming Subscription Expiry', 7 | 'no_upcoming_subscriptions_expiry' => 'No upcoming expiry within next 60 days.', 8 | 'yearly_earnings' => 'Yearly Earnings', 9 | 'finished_projects_count' => 'Finished projects', 10 | 'receiveable_earnings' => 'Receiveable Earnings', 11 | ]; 12 | -------------------------------------------------------------------------------- /resources/views/layouts/partials/noty.blade.php: -------------------------------------------------------------------------------- 1 | @if(Session::has('flash_notification.message')) 2 | @php 3 | $level = Session::get('flash_notification.level'); 4 | if ($level == 'info') { 5 | $level = 'information'; 6 | } 7 | @endphp 8 | 9 | 17 | @endif 18 | -------------------------------------------------------------------------------- /app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | 'Settings', 6 | 'create' => 'Add New Option', 7 | 'created' => 'New Option created.', 8 | 'updated' => 'Option updated.', 9 | 'delete' => 'Delete Option', 10 | 'deleted' => 'Option deleted.', 11 | 'undeleted' => 'Option cannot be deleted.', 12 | 'key' => 'Key', 13 | 'value' => 'Value', 14 | 15 | // Keys 16 | 'money_sign' => 'Money Sign', 17 | 'money_sign_in_word' => 'Money Sign in Word', 18 | ]; 19 | -------------------------------------------------------------------------------- /resources/lang/id/dashboard.php: -------------------------------------------------------------------------------- 1 | 'Statistik Status Project', 5 | 'earnings_stats' => 'Statistik Pendapatan', 6 | 'upcoming_subscriptions_expiry' => 'Langganan akan Berakhir', 7 | 'no_upcoming_subscriptions_expiry' => 'Belum ada Langganan yang akan berakhir dalam 60 hari ke depan.', 8 | 'yearly_earnings' => 'Pendapatan Tahunan', 9 | 'finished_projects_count' => 'Project Selesai', 10 | 'receiveable_earnings' => 'Piutang', 11 | ]; 12 | -------------------------------------------------------------------------------- /resources/views/layouts/project.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title') 4 | @yield('subtitle', __('project.detail')) - {{ $project->name }} 5 | @endsection 6 | 7 | @section('content') 8 | @include('projects.partials.breadcrumb') 9 | 10 |

    11 |
    12 | @yield('action-buttons') 13 |
    14 | {{ $project->name }} @yield('subtitle', __('project.detail')) 15 |

    16 | 17 | @include('projects.partials.nav-tabs') 18 | 19 | @yield('content-project') 20 | 21 | @endsection 22 | -------------------------------------------------------------------------------- /routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 16 | }); 17 | -------------------------------------------------------------------------------- /resources/views/view-components/sidebar-project-list-links.blade.php: -------------------------------------------------------------------------------- 1 | @inject('projectStatuses', 'App\Entities\Projects\Status') 2 | 3 | 13 | -------------------------------------------------------------------------------- /app/Http/Controllers/Users/JobsController.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class JobsController extends Controller 15 | { 16 | public function index(User $user) 17 | { 18 | $jobs = (new AdminDashboardQuery())->onProgressJobs($user, ['project']); 19 | 20 | return view('users.jobs', compact('user', 'jobs')); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resources/lang/de/option.php: -------------------------------------------------------------------------------- 1 | 'Einstellungen', 6 | 'create' => 'neue Option hinzufügen', 7 | 'created' => 'Neue Option erstellt.', 8 | 'updated' => 'Option aktualisiert.', 9 | 'delete' => 'Option löschen', 10 | 'deleted' => 'Option gelöscht.', 11 | 'undeleted' => 'Option kann nicht gelöscht werden.', 12 | 'key' => 'Schlüssel', 13 | 'value' => 'Wert', 14 | 15 | // Keys 16 | 'money_sign' => 'Geldsignatur', 17 | 'money_sign_in_word' => 'Money Sign in Word', 18 | ]; 19 | -------------------------------------------------------------------------------- /routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 18 | }); 19 | -------------------------------------------------------------------------------- /resources/lang/de/dashboard.php: -------------------------------------------------------------------------------- 1 | 'Projektstatus Satistik', 5 | 'earnings_stats' => 'Verdienst Statistik', 6 | 'upcoming_subscriptions_expiry' => 'kommende auslaufende Abonnement', 7 | 'no_upcoming_subscriptions_expiry' => 'Keine kommende auslaufende Abonnements in den nächsten 60 Tagen.', 8 | 'yearly_earnings' => 'jährliche Verdienste', 9 | 'finished_projects_count' => 'abgeschlossene Projekte', 10 | 'receiveable_earnings' => 'empfangbare Verdienste', 11 | ]; 12 | -------------------------------------------------------------------------------- /resources/lang/id/option.php: -------------------------------------------------------------------------------- 1 | 'Pengaturan', 6 | 'create' => 'Buat Option Baru', 7 | 'created' => 'Option baru berhasil dibuat.', 8 | 'updated' => 'Option berhasil disimpan.', 9 | 'delete' => 'Hapus Option', 10 | 'deleted' => 'Option berhasil dihapus.', 11 | 'undeleted' => 'Option tidak berhasil dihapus.', 12 | 'key' => 'Key', 13 | 'value' => 'Value', 14 | 15 | // Keys 16 | 'money_sign' => 'Tanda Mata Uang', 17 | 'money_sign_in_word' => 'Tanda Mata Uang Terbilang', 18 | ]; 19 | -------------------------------------------------------------------------------- /app/Entities/Users/Activity.php: -------------------------------------------------------------------------------- 1 | 'array']; 14 | 15 | public function user() 16 | { 17 | return $this->belongsTo(User::class)->withDefault(['name' => 'n/a']); 18 | } 19 | 20 | public function object() 21 | { 22 | return $this->morphTo(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /public/assets/css/plugins/metisMenu/metisMenu.min.css: -------------------------------------------------------------------------------- 1 | .arrow{float:right}.glyphicon.arrow:before{content:"\e079"}.active>a>.glyphicon.arrow:before{content:"\e114"}.fa.arrow:before{content:"\f104"}.active>a>.fa.arrow:before{content:"\f107"}.plus-times{float:right}.fa.plus-times:before{content:"\f067"}.active>a>.fa.plus-times{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.plus-minus{float:right}.fa.plus-minus:before{content:"\f067"}.active>a>.fa.plus-minus:before{content:"\f068"} -------------------------------------------------------------------------------- /resources/lang/de/time.php: -------------------------------------------------------------------------------- 1 | 'Day(s)', 5 | 'date' => 'Datum', 6 | 'month' => 'Monat', 7 | 'week' => 'week', 8 | 9 | 'months' => [ 10 | '01' => 'Januar', 11 | '02' => 'Februari', 12 | '03' => 'März', 13 | '04' => 'April', 14 | '05' => 'Kann', 15 | '06' => 'June', 16 | '07' => 'July', 17 | '08' => 'August', 18 | '09' => 'September', 19 | '10' => 'Oktober', 20 | '11' => 'November', 21 | '12' => 'Dezember', 22 | ], 23 | 24 | 'updated_at' => 'Last Update', 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/en/time.php: -------------------------------------------------------------------------------- 1 | 'Day(s)', 5 | 'date' => 'Date', 6 | 'month' => 'Month', 7 | 'week' => 'Week', 8 | 9 | 'months' => [ 10 | '01' => 'January', 11 | '02' => 'Februari', 12 | '03' => 'March', 13 | '04' => 'April', 14 | '05' => 'May', 15 | '06' => 'June', 16 | '07' => 'July', 17 | '08' => 'August', 18 | '09' => 'September', 19 | '10' => 'October', 20 | '11' => 'November', 21 | '12' => 'December', 22 | ], 23 | 24 | 'updated_at' => 'Last Update', 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/id/time.php: -------------------------------------------------------------------------------- 1 | 'Hari', 5 | 'date' => 'Tanggal', 6 | 'month' => 'Bulan', 7 | 'week' => 'Minggu', 8 | 9 | 'months' => [ 10 | '01' => 'Januari', 11 | '02' => 'Februari', 12 | '03' => 'Maret', 13 | '04' => 'April', 14 | '05' => 'Mei', 15 | '06' => 'Juni', 16 | '07' => 'Juli', 17 | '08' => 'Agustus', 18 | '09' => 'September', 19 | '10' => 'Oktober', 20 | '11' => 'November', 21 | '12' => 'Desember', 22 | ], 23 | 24 | 'updated_at' => 'Update Terakhir', 25 | ]; 26 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 7 | */ 8 | $uri = urldecode( 9 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 10 | ); 11 | 12 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 13 | // built-in PHP web server. This provides a convenient way to test a Laravel 14 | // application without having installed a "real" web server software here. 15 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 16 | return false; 17 | } 18 | 19 | require_once __DIR__.'/public/index.php'; 20 | -------------------------------------------------------------------------------- /resources/views/users/activities/jobs/task_deleted.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 |

    7 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 8 | 'user' => $activity->user->name, 9 | ]) !!} 10 |

    11 |
    {{ __('task.name') }}: {{ $activity->data['name'] }}
    12 |
    {{ __('task.description') }}: {{ $activity->data['description'] }}
    13 |
    {{ __('task.progress') }}: {{ $activity->data['progress'] }} %
    14 | @endslot 15 | @endcomponent 16 | -------------------------------------------------------------------------------- /resources/views/layouts/print.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | @yield('title', Option::get('app_name', 'Aplikasi Laravel')) 10 | 11 | {!! Html::style('assets/css/print.css') !!} 12 | @yield('style') 13 | 14 | 15 | @yield('content') 16 | {!! Html::script(url('assets/js/jquery.js')) !!} 17 | 18 | 19 | -------------------------------------------------------------------------------- /resources/views/users/activities/projects/job_deleted.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 |

    7 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 8 | 'user' => $activity->user->name, 9 | ]) !!} 10 |

    11 |
    {{ __('job.name') }}: {{ $activity->data['name'] }}
    12 |
    {{ __('job.description') }}: {{ $activity->data['description'] }}
    13 |
    {{ __('job.price') }}: {{ format_money($activity->data['price']) }}
    14 | @endslot 15 | @endcomponent 16 | -------------------------------------------------------------------------------- /app/Policies/EventPolicy.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class EventPolicy 15 | { 16 | use HandlesAuthorization; 17 | 18 | public function update(User $user, Event $event) 19 | { 20 | return $user->id == $event->user_id; 21 | } 22 | 23 | public function delete(User $user, Event $event) 24 | { 25 | return $user->id == $event->user_id; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /database/factories/CommentFactory.php: -------------------------------------------------------------------------------- 1 | define(Comment::class, function (Faker $faker) { 9 | return [ 10 | 'commentable_type' => 'projects', 11 | 'commentable_id' => function () { 12 | return factory(Project::class)->create()->id; 13 | }, 14 | 'body' => $faker->sentence, 15 | 'creator_id' => function () { 16 | return factory(User::class)->create()->id; 17 | }, 18 | ]; 19 | }); 20 | -------------------------------------------------------------------------------- /resources/lang/de/pagination.php: -------------------------------------------------------------------------------- 1 | '« Letzte', 17 | 'next' => 'Nächste »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Redirect Trailing Slashes If Not A Folder... 9 | RewriteCond %{REQUEST_FILENAME} !-d 10 | RewriteRule ^(.*)/$ /$1 [L,R=301] 11 | 12 | # Handle Front Controller... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_FILENAME} !-f 15 | RewriteRule ^ index.php [L] 16 | 17 | # Handle Authorization Header 18 | RewriteCond %{HTTP:Authorization} . 19 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 20 | 21 | -------------------------------------------------------------------------------- /app/Entities/Options/Option.php: -------------------------------------------------------------------------------- 1 | belongsTo(User::class); 15 | } 16 | 17 | public function getTimeDisplayAttribute() 18 | { 19 | if (now()->format('Y-m-d') != $this->created_at->format('Y-m-d')) { 20 | return $this->created_at; 21 | } 22 | 23 | return $this->created_at->diffForHumans(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Entities/Projects/ProjectPresenter.php: -------------------------------------------------------------------------------- 1 | customer_id ? $this->customer->name.' ('.$this->customer->email.')' : '-'; 13 | } 14 | 15 | public function projectLink() 16 | { 17 | return link_to_route('projects.show', $this->name, [$this->id]); 18 | } 19 | 20 | public function status() 21 | { 22 | return ProjectStatus::getNameById($this->entity->status_id); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/Entities/Invoices/BankAccount.php: -------------------------------------------------------------------------------- 1 | is_active == 1 ? __('app.active') : __('app.in_active'); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Entities/Projects/JobPresenter.php: -------------------------------------------------------------------------------- 1 | worker_id ? $this->worker->name.' ('.$this->worker->email.')' : '-'; 12 | } 13 | 14 | public function projectLink() 15 | { 16 | return link_to_route('projects.show', $this->project->name, [$this->project_id]); 17 | } 18 | 19 | public function projectJobsLink() 20 | { 21 | return link_to_route('projects.jobs.index', __('project.jobs'), [$this->project_id]); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/Http/Middleware/RedirectIfAuthenticated.php: -------------------------------------------------------------------------------- 1 | check()) { 21 | return redirect('/'); 22 | } 23 | 24 | return $next($request); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/Listeners/Jobs/LogJobCreationActivity.php: -------------------------------------------------------------------------------- 1 | job; 13 | 14 | $activityEntry = [ 15 | 'type' => 'job_created', 16 | 'parent_id' => null, 17 | 'user_id' => auth()->id(), 18 | 'object_id' => $job->id, 19 | 'object_type' => 'jobs', 20 | 'data' => null, 21 | ]; 22 | 23 | Activity::create($activityEntry); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/Listeners/Projects/LogProjectCreationActivity.php: -------------------------------------------------------------------------------- 1 | project; 13 | 14 | $activityEntry = [ 15 | 'type' => 'project_created', 16 | 'parent_id' => null, 17 | 'user_id' => auth()->id(), 18 | 'object_id' => $project->id, 19 | 'object_type' => 'projects', 20 | ]; 21 | 22 | Activity::create($activityEntry); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/views/layouts/customer.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', trans('customer.detail')) 4 | 5 | @section('content') 6 |

    7 |
    8 | {!! link_to_route('customers.edit', trans('customer.edit'), [$customer->id], ['id' => 'edit-customer-' . $customer->id, 'class' => 'btn btn-warning']) !!} 9 | {!! link_to_route('customers.index', trans('customer.back_to_index'), [], ['class' => 'btn btn-default']) !!} 10 |
    11 | 12 | {{ $customer->name }} @yield('title') 13 |

    14 | @include('customers.partials.nav-tabs') 15 | @yield('content-customer') 16 | @endsection 17 | -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 26 | 27 | return $app; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Listeners/Tasks/LogTaskCreationActivity.php: -------------------------------------------------------------------------------- 1 | task; 13 | 14 | $activityEntry = [ 15 | 'type' => 'task_created', 16 | 'parent_id' => null, 17 | 'user_id' => auth()->id(), 18 | 'object_id' => $task->id, 19 | 'object_type' => 'tasks', 20 | 'data' => null, 21 | ]; 22 | 23 | Activity::create($activityEntry); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /resources/views/layouts/job.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title') 4 | @yield('subtitle', __('job.detail')) - {{ $job->name }} 5 | @endsection 6 | 7 | @section('content') 8 | @include('jobs.partials.breadcrumb') 9 | 10 |

    11 |
    12 | @yield('action-buttons') 13 | {{ link_to_route('projects.jobs.index', __('job.back_to_index'), [$job->project_id, '#' . $job->id], ['class' => 'btn btn-default']) }} 14 |
    15 | {{ $job->name }} @yield('subtitle', __('job.detail')) 16 |

    17 | 18 | @include('jobs.partials.nav-tabs') 19 | 20 | @yield('content-job') 21 | 22 | @endsection 23 | -------------------------------------------------------------------------------- /tests/Unit/Models/BankAccountTest.php: -------------------------------------------------------------------------------- 1 | make(['is_active' => 1]); 17 | $this->assertEquals(__('app.active'), $bankAccount->status); 18 | 19 | $bankAccount->is_active = 0; 20 | $this->assertEquals(__('app.in_active'), $bankAccount->status); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Controllers/Users/CalendarController.php: -------------------------------------------------------------------------------- 1 | user(); 13 | 14 | if ($user->hasRole('admin') == false) { 15 | $projects = $user->projects()->orderBy('projects.name')->pluck('projects.name', 'projects.id'); 16 | } else { 17 | $projects = Project::orderBy('name')->pluck('name', 'id'); 18 | } 19 | 20 | return view('users.calendar', compact('projects')); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/Http/Requests/Request.php: -------------------------------------------------------------------------------- 1 | user(); 10 | $queriedYear = request('year', date('Y')); 11 | 12 | $userCurrentJobs = $user->jobs() 13 | ->whereHas('project', function ($query) { 14 | $query->whereIn('status_id', [2, 3]); 15 | })->with('tasks')->get(); 16 | 17 | return view('pages.home', compact('queriedYear', 'user', 'userCurrentJobs')); 18 | } 19 | 20 | public function about() 21 | { 22 | return view('pages.about'); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /resources/lang/id/pagination.php: -------------------------------------------------------------------------------- 1 | '« Sebelumnya', 17 | 'next' => 'Berikutnya »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel application. By default, we are compiling the Sass 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/assets/js/app.js', 'public/assets/js') 15 | .options({ 16 | processCssUrls: false 17 | }) 18 | .sass('resources/assets/sass/app.scss', 'public/assets/css'); 19 | -------------------------------------------------------------------------------- /database/factories/IssueFactory.php: -------------------------------------------------------------------------------- 1 | define(Issue::class, function (Faker $faker) { 9 | return [ 10 | 'project_id' => function () { 11 | return factory(Project::class)->create()->id; 12 | }, 13 | 'title' => $faker->words(3, true), 14 | 'body' => $faker->sentences(3, true), 15 | 'creator_id' => function () { 16 | return factory(User::class)->create()->id; 17 | }, 18 | 'status_id' => 0, 19 | 'priority_id' => 1, 20 | ]; 21 | }); 22 | -------------------------------------------------------------------------------- /app/Http/Requests/Payments/DeleteRequest.php: -------------------------------------------------------------------------------- 1 | user()->can('manage_payments'); 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 | 'payment_id' => 'required', 28 | ]; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/views/payments/delete.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', __('payment.delete')) 4 | 5 | @section('content') 6 |

    7 |
    8 | {!! FormField::delete(['route'=>['payments.destroy',$payment->id]], __('app.delete_confirm_button'), ['class'=>'btn btn-danger'], ['payment_id'=>$payment->id]) !!} 9 |
    10 | {{ __('app.delete_confirm') }} 11 | {!! link_to_route('payments.show', __('app.cancel'), [$payment->id], ['class' => 'btn btn-default']) !!} 12 |

    13 |
    14 |
    15 | @include('payments.partials.payment-show') 16 |
    17 |
    18 | @endsection 19 | -------------------------------------------------------------------------------- /app/Entities/Projects/Task.php: -------------------------------------------------------------------------------- 1 | 'App\Events\Tasks\Created', 16 | 'updated' => 'App\Events\Tasks\Updated', 17 | 'deleted' => 'App\Events\Tasks\Deleted', 18 | ]; 19 | 20 | protected $guarded = ['id', 'created_at', 'updated_at']; 21 | 22 | protected $touches = ['job']; 23 | 24 | public function job() 25 | { 26 | return $this->belongsTo(Job::class, 'job_id'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /resources/views/projects/activities/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.project') 2 | 3 | @section('subtitle', __('project.activities')) 4 | 5 | @section('content-project') 6 | 7 |
    8 |
    9 | {{ $activities->links() }} 10 | 18 | {{ $activities->links() }} 19 |
    20 |
    21 | 22 | @endsection 23 | -------------------------------------------------------------------------------- /resources/views/projects/delete.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', trans('project.delete')) 4 | 5 | @section('content') 6 |

    7 |
    8 | {!! FormField::delete(['route'=>['projects.destroy',$project->id]], trans('app.delete_confirm_button'), ['class'=>'btn btn-danger'], ['project_id'=>$project->id]) !!} 9 |
    10 | {{ trans('app.delete_confirm') }} 11 | {!! link_to_route('projects.show', trans('app.cancel'), [$project->id], ['class' => 'btn btn-default']) !!} 12 |

    13 |
    14 |
    15 | @include('projects.partials.project-show') 16 |
    17 |
    18 | @endsection 19 | -------------------------------------------------------------------------------- /database/factories/InvoiceFactory.php: -------------------------------------------------------------------------------- 1 | define(Invoice::class, function (Faker $faker) { 9 | return [ 10 | 'project_id' => function () { 11 | return factory(Project::class)->create()->id; 12 | }, 13 | 'number' => (new Invoice())->generateNewNumber(), 14 | 'items' => [], 15 | 'date' => '2010-10-10', 16 | 'amount' => 100000, 17 | 'status_id' => 1, 18 | 'creator_id' => function () { 19 | return factory(User::class)->create()->id; 20 | }, 21 | ]; 22 | }); 23 | -------------------------------------------------------------------------------- /app/Policies/Projects/IssuePolicy.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class ProjectsController extends Controller 14 | { 15 | /** 16 | * Project list of a customer. 17 | * 18 | * @param \App\Entities\Partners\Customer $customer 19 | * @return \Illuminate\View\View 20 | */ 21 | public function index(Customer $customer) 22 | { 23 | $projects = $customer->projects; 24 | 25 | return view('customers.projects', compact('customer', 'projects')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /resources/views/users/activities/tasks/task_updated.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 |

    7 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 8 | 'user' => $activity->user->name, 9 | 'name' => $activity->object->name, 10 | ]) !!} 11 |

    12 | @php 13 | $data = $activity->data; 14 | @endphp 15 | @foreach ($data['before'] as $key => $value) 16 | @php 17 | $afterValue = $data['after'][$key] ?? null; 18 | @endphp 19 |
    {{ __('job.'.$key) }}: {{ $value }} => {{ $afterValue }}
    20 | @endforeach 21 | @endslot 22 | @endcomponent 23 | -------------------------------------------------------------------------------- /app/Console/Commands/Inspire.php: -------------------------------------------------------------------------------- 1 | comment(PHP_EOL.Inspiring::quote().PHP_EOL); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Http/Controllers/Customers/InvoicesController.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class InvoicesController extends Controller 14 | { 15 | /** 16 | * Invoice list of a customer. 17 | * 18 | * @param \App\Entities\Partners\Customer $customer 19 | * @return \Illuminate\View\View 20 | */ 21 | public function index(Customer $customer) 22 | { 23 | $invoices = $customer->invoices()->orderBy('date', 'desc')->get(); 24 | 25 | return view('customers.invoices', compact('customer', 'invoices')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/Http/Requests/Tasks/DeleteRequest.php: -------------------------------------------------------------------------------- 1 | user()->can( 17 | 'delete', $this->route('task') 18 | ); 19 | } 20 | 21 | /** 22 | * Get the validation rules that apply to the request. 23 | * 24 | * @return array 25 | */ 26 | public function rules() 27 | { 28 | return [ 29 | 'task_id' => 'required', 30 | 'job_id' => 'required', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Console/Kernel.php: -------------------------------------------------------------------------------- 1 | command('inspire') 28 | // ->hourly(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/views/users/profile/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.dashboard') 2 | 3 | @section('title', trans('auth.profile_edit')) 4 | 5 | @section('content-dashboard') 6 |
    7 |
    8 | {{ Form::model(auth()->user(), ['route' => 'users.profile.update', 'method' => 'patch']) }} 9 | {!! FormField::text('name') !!} 10 | {!! FormField::email('email') !!} 11 | {!! FormField::radios('lang', $langList, ['label' => trans('lang.lang')]) !!} 12 | {{ Form::submit(trans('auth.update_profile'), ['class' => 'btn btn-info']) }} 13 | {{ link_to_route('users.profile.show', trans('app.cancel'), [], ['class' => 'btn btn-default']) }} 14 | {{ Form::close() }} 15 |
    16 |
    17 | 18 | @endsection 19 | -------------------------------------------------------------------------------- /database/migrations/2015_07_14_131409_create_site_options_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('key', 60)->index(); 18 | $table->string('value'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('site_options'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Entities/Payments/PaymentPresenter.php: -------------------------------------------------------------------------------- 1 | entity->in_out == 0 ? format_money(-$this->entity->amount) : format_money($this->entity->amount); 12 | } 13 | 14 | public function projectLink() 15 | { 16 | return link_to_route('projects.show', $this->project->name, [$this->project_id]); 17 | } 18 | 19 | public function projectPaymentsLink() 20 | { 21 | return link_to_route('projects.payments', __('project.payments'), [$this->project_id]); 22 | } 23 | 24 | public function type() 25 | { 26 | return paymentTypes($this->entity->type_id); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tests/Feature/Api/ApiManageProjectsTest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class ApiManageProjectsTest extends TestCase 15 | { 16 | use RefreshDatabase; 17 | 18 | /** @test */ 19 | public function user_can_get_project_lists() 20 | { 21 | $user = $this->adminUserSigningIn(); 22 | $project = factory(Project::class, 1)->create(); 23 | 24 | $this->getJson(route('api.projects.index'), [ 25 | 'Authorization' => 'Bearer '.$user->api_token, 26 | ]); 27 | 28 | $this->seeStatusCode(200); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Http/Controllers/Customers/SubscriptionsController.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class SubscriptionsController extends Controller 14 | { 15 | /** 16 | * Subscription list of a customer. 17 | * 18 | * @param \App\Entities\Partners\Customer $customer 19 | * @return \Illuminate\View\View 20 | */ 21 | public function index(Customer $customer) 22 | { 23 | $subscriptions = $customer->subscriptions()->orderBy('due_date')->get(); 24 | 25 | return view('customers.subscriptions', compact('customer', 'subscriptions')); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /resources/views/jobs/delete.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', __('job.delete')) 4 | 5 | @section('content') 6 |

    7 |
    8 | {!! FormField::delete([ 9 | 'route' => ['jobs.destroy', $job]], 10 | __('app.delete_confirm_button'), 11 | ['class' => 'btn btn-danger'], 12 | [ 13 | 'job_id' => $job->id, 14 | 'project_id' => $job->project_id, 15 | ]) !!} 16 |
    17 | {{ __('app.delete_confirm') }} 18 | {{link_to_route('jobs.show', __('app.cancel'), [$job], ['class' => 'btn btn-default']) }} 19 |

    20 |
    21 |
    22 | @include('jobs.partials.job-show') 23 |
    24 |
    25 | @endsection 26 | -------------------------------------------------------------------------------- /app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | guest()) { 21 | if ($request->ajax() || $request->wantsJson()) { 22 | return response('Unauthorized.', 401); 23 | } else { 24 | return redirect()->guest('login'); 25 | } 26 | } 27 | 28 | return $next($request); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 17 | $table->string('token')->index(); 18 | $table->timestamp('created_at'); 19 | }); 20 | } 21 | 22 | /** 23 | * Reverse the migrations. 24 | * 25 | * @return void 26 | */ 27 | public function down() 28 | { 29 | Schema::drop('password_resets'); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/Http/Controllers/Projects/InvoicesController.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class InvoicesController extends Controller 14 | { 15 | /** 16 | * Invoice list of a project. 17 | * 18 | * @param \App\Entities\Projects\Project $project 19 | * @return \Illuminate\View\View 20 | */ 21 | public function index(Project $project) 22 | { 23 | $this->authorize('view-invoices', $project); 24 | 25 | $invoices = $project->invoices()->orderBy('date', 'desc')->get(); 26 | 27 | return view('projects.invoices', compact('project', 'invoices')); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/Http/Controllers/Customers/PaymentsController.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class PaymentsController extends Controller 14 | { 15 | /** 16 | * Payment list of a customer. 17 | * 18 | * @param \App\Entities\Partners\Customer $customer 19 | * @return \Illuminate\View\View 20 | */ 21 | public function index(Customer $customer) 22 | { 23 | $payments = $customer->payments() 24 | ->latest() 25 | ->with('project') 26 | ->get(); 27 | 28 | return view('customers.payments', compact('customer', 'payments')); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /resources/views/layouts/partials/lang-switcher.blade.php: -------------------------------------------------------------------------------- 1 |
    2 | {{ trans('lang.lang') }} : 3 | 4 | @foreach (['en', 'id', 'de'] as $langKey) 5 | {!! FormField::formButton( 6 | [ 7 | 'route' => 'users.profile.switch-lang', 8 | 'method' => 'patch', 9 | 'title' => auth()->user()->lang != $langKey ? trans('lang.switch_tooltip', ['lang' => trans('lang.'.$langKey)]) : '' 10 | ], 11 | strtoupper($langKey), 12 | ['class' => 'btn btn-default btn-xs', 'id' => 'switch_lang_'.$langKey] 13 | + (auth()->user()->lang == $langKey ? ['disabled' => 'disabled'] : []), 14 | ['lang' => $langKey] 15 | ) !!} 16 | @endforeach 17 |
    18 | -------------------------------------------------------------------------------- /resources/views/payments/partials/payment-show.blade.php: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
    {{ __('payment.id') }}#{{ $payment->id }}
    {{ __('payment.date') }}{{ $payment->date }}
    {{ __('payment.in_out') }}{{ $payment->in_out ? __('payment.cash_in') : __('payment.cash_out') }}
    {{ __('payment.customer') }}{{ $payment->partner->name }}
    {{ __('payment.amount') }}{{ $payment->present()->amount }}
    {{ __('payment.description') }}{{ $payment->description }}
    12 |
    13 | -------------------------------------------------------------------------------- /app/Entities/Projects/Priority.php: -------------------------------------------------------------------------------- 1 | 'minor', 11 | 2 => 'major', 12 | 3 => 'critical', 13 | ]; 14 | 15 | protected static $colors = [ 16 | 1 => 'info', 17 | 2 => 'warning', 18 | 3 => 'danger', 19 | ]; 20 | 21 | public static function getNameById($singleId) 22 | { 23 | return __('issue.'.static::getById($singleId)); 24 | } 25 | 26 | public static function toArray() 27 | { 28 | $lists = []; 29 | foreach (static::$lists as $key => $value) { 30 | $lists[$key] = __('issue.'.$value); 31 | } 32 | 33 | return $lists; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Controllers/Users/ProjectsController.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class ProjectsController extends Controller 14 | { 15 | public function index(User $user) 16 | { 17 | $projects = $user->projects() 18 | ->where(function ($query) { 19 | $query->where('projects.name', 'like', '%'.request('q').'%'); 20 | $query->where('status_id', request('status', 2)); 21 | }) 22 | ->latest() 23 | ->with(['customer']) 24 | ->paginate(); 25 | 26 | return view('users.projects', compact('user', 'projects')); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /resources/lang/de/comment.php: -------------------------------------------------------------------------------- 1 | 'Comment', 6 | 'list' => 'Comments', 7 | 'empty' => 'Comment is empty.', 8 | 9 | // Actions 10 | 'create' => 'Add Comment', 11 | 'create_text' => 'Write your comment ...', 12 | 'created' => 'Create new Comment succeded.', 13 | 'edit' => 'Edit Comment', 14 | 'update' => 'Update Comment', 15 | 'updated' => 'Update Comment succeded.', 16 | 'delete' => 'Delete Comment', 17 | 'delete_confirm' => 'Are you sure to delete this Comment?', 18 | 'deleted' => 'Delete Comment succeded.', 19 | 'undeleted' => 'Comment not deleted.', 20 | 'undeleteable' => 'Comment cannot be deleted.', 21 | 22 | // Attributes 23 | 'body' => 'Comment', 24 | ]; 25 | -------------------------------------------------------------------------------- /resources/lang/en/comment.php: -------------------------------------------------------------------------------- 1 | 'Comment', 6 | 'list' => 'Comments', 7 | 'empty' => 'Comment is empty.', 8 | 9 | // Actions 10 | 'create' => 'Add Comment', 11 | 'create_text' => 'Write your comment ...', 12 | 'created' => 'Create new Comment succeded.', 13 | 'edit' => 'Edit Comment', 14 | 'update' => 'Update Comment', 15 | 'updated' => 'Update Comment succeded.', 16 | 'delete' => 'Delete Comment', 17 | 'delete_confirm' => 'Are you sure to delete this Comment?', 18 | 'deleted' => 'Delete Comment succeded.', 19 | 'undeleted' => 'Comment not deleted.', 20 | 'undeleteable' => 'Comment cannot be deleted.', 21 | 22 | // Attributes 23 | 'body' => 'Comment', 24 | ]; 25 | -------------------------------------------------------------------------------- /app/Http/Requests/Jobs/DeleteRequest.php: -------------------------------------------------------------------------------- 1 | get('project_id')); 18 | 19 | return auth()->user()->can('manage_jobs', $project); 20 | } 21 | 22 | /** 23 | * Get the validation rules that apply to the request. 24 | * 25 | * @return array 26 | */ 27 | public function rules() 28 | { 29 | return [ 30 | 'job_id' => 'required', 31 | 'project_id' => 'required', 32 | ]; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Requests/Tasks/CreateRequest.php: -------------------------------------------------------------------------------- 1 | user()->can('create', new Task()); 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|max:60', 29 | 'description' => 'nullable|max:255', 30 | 'progress' => 'required|numeric|max:100', 31 | ]; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/Entities/Payments/Type.php: -------------------------------------------------------------------------------- 1 | 'project', 11 | 2 => 'add_job', 12 | 3 => 'maintenance', 13 | ]; 14 | 15 | protected static $colors = [ 16 | 1 => '#337ab7', 17 | 2 => '#4caf50', 18 | 3 => '#ff8181', 19 | ]; 20 | 21 | public static function getNameById($singleId) 22 | { 23 | return __('payment.types.'.static::getById($singleId)); 24 | } 25 | 26 | public static function toArray() 27 | { 28 | $lists = []; 29 | foreach (static::$lists as $key => $value) { 30 | $lists[$key] = __('payment.types.'.$value); 31 | } 32 | 33 | return $lists; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/lang/id/comment.php: -------------------------------------------------------------------------------- 1 | 'Komentar', 6 | 'list' => 'List Komentar', 7 | 'empty' => 'Belum ada Komentar', 8 | 9 | // Actions 10 | 'create' => 'Tambah Komentar', 11 | 'create_text' => 'Tulis komentar anda ...', 12 | 'created' => 'Input Komentar berhasil.', 13 | 'edit' => 'Edit Komentar', 14 | 'update' => 'Update Komentar', 15 | 'updated' => 'Update Komentar berhasil.', 16 | 'delete' => 'Hapus Komentar', 17 | 'delete_confirm' => 'Anda yakin akan menghapus Komentar ini?', 18 | 'deleted' => 'Komentar berhasil dihapus.', 19 | 'undeleted' => 'Komentar gagal dihapus.', 20 | 'undeleteable' => 'Komentar tidak dapat dihapus.', 21 | 22 | // Attributes 23 | 'body' => 'Komentar', 24 | ]; 25 | -------------------------------------------------------------------------------- /app/Http/Controllers/Issues/OptionController.php: -------------------------------------------------------------------------------- 1 | validate([ 14 | 'priority_id' => 'required|in:1,2,3', 15 | 'status_id' => 'required|in:0,1,2,3,4', 16 | 'pic_id' => 'nullable|exists:users,id', 17 | ]); 18 | $issue->priority_id = $issueData['priority_id']; 19 | $issue->status_id = $issueData['status_id']; 20 | $issue->pic_id = $issueData['pic_id']; 21 | $issue->save(); 22 | flash(__('issue.updated'), 'success'); 23 | 24 | return back(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_NAME="Free-PMO" 2 | APP_ENV=local 3 | APP_KEY=SomeRandomString 4 | APP_DEBUG=true 5 | APP_LOG_LEVEL=debug 6 | APP_URL=http://localhost 7 | 8 | LOG_CHANNEL=stack 9 | APP_TIMEZONE=Asia/Makassar 10 | 11 | DB_CONNECTION=mysql 12 | DB_HOST=127.0.0.1 13 | DB_DATABASE=homestead 14 | DB_USERNAME=homestead 15 | DB_PASSWORD=secret 16 | 17 | BROADCAST_DRIVER=log 18 | CACHE_DRIVER=file 19 | SESSION_DRIVER=file 20 | QUEUE_DRIVER=sync 21 | 22 | REDIS_HOST=127.0.0.1 23 | REDIS_PASSWORD=null 24 | REDIS_PORT=6379 25 | 26 | MAIL_DRIVER=smtp 27 | MAIL_HOST=mailtrap.io 28 | MAIL_PORT=2525 29 | MAIL_USERNAME=null 30 | MAIL_PASSWORD=null 31 | MAIL_ENCRYPTION=null 32 | MAIL_FROM=null 33 | MAIL_NAME=null 34 | 35 | PUSHER_APP_ID= 36 | PUSHER_APP_KEY= 37 | PUSHER_APP_SECRET= 38 | PUSHER_APP_CLUSTER=mt1 39 | 40 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 41 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" -------------------------------------------------------------------------------- /resources/views/subscriptions/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', $pageTitle) 4 | 5 | @section('content') 6 | @include('subscriptions.partials.breadcrumb') 7 | 8 |
    9 |
    10 |
    11 |

    {{ $pageTitle }}

    12 | @include('subscriptions.partials.subscription-show') 13 |
    14 |
    15 |
    16 | {{ __('app.action') }} 17 |

    {!! link_to_route('subscriptions.edit', __('subscription.edit'), [$subscription->id], ['class' => 'btn btn-warning']) !!}

    18 |

    {!! link_to_route('subscriptions.index', __('subscription.back_to_index'), [], ['class' => 'btn btn-default']) !!}

    19 |
    20 |
    21 | @endsection 22 | -------------------------------------------------------------------------------- /tests/Unit/Policies/IssuePolicyTest.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class IssuePolicyTest extends TestCase 15 | { 16 | use RefreshDatabase; 17 | 18 | /** @test */ 19 | public function admin_can_create_issue() 20 | { 21 | $admin = $this->createUser('admin'); 22 | 23 | $this->assertTrue($admin->can('create', new Issue())); 24 | } 25 | 26 | /** @test */ 27 | public function admin_can_add_comment_to_an_issue() 28 | { 29 | $admin = $this->createUser('admin'); 30 | $issue = factory(Issue::class)->create(); 31 | 32 | $this->assertTrue($admin->can('comment-on', $issue)); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Http/Middleware/GlobalViewVariables.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class GlobalViewVariables 15 | { 16 | /** 17 | * Handle an incoming request. 18 | * 19 | * @param \Illuminate\Http\Request $request 20 | * @param \Closure $next 21 | * @return mixed 22 | */ 23 | public function handle($request, Closure $next) 24 | { 25 | $projectsCount = Project::select(DB::raw('status_id, count(id) as count')) 26 | ->groupBy('status_id') 27 | ->pluck('count', 'status_id') 28 | ->all(); 29 | 30 | view()->share('projectStatusStats', $projectsCount); 31 | 32 | return $next($request); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/Listeners/Jobs/LogJobTaskDeletionActivity.php: -------------------------------------------------------------------------------- 1 | task; 13 | $jobId = $task->job_id; 14 | 15 | $activityEntry = [ 16 | 'type' => 'task_deleted', 17 | 'parent_id' => null, 18 | 'user_id' => auth()->id(), 19 | 'object_id' => $jobId, 20 | 'object_type' => 'jobs', 21 | 'data' => [ 22 | 'name' => $task->name, 23 | 'description' => $task->description, 24 | 'progress' => $task->progress, 25 | ], 26 | ]; 27 | 28 | Activity::create($activityEntry); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /database/migrations/2017_11_14_061927_create_user_roles_table.php: -------------------------------------------------------------------------------- 1 | unsignedInteger('user_id'); 18 | $table->unsignedTinyInteger('role_id'); 19 | 20 | $table->unique(['user_id', 'role_id'], 'user_role_unique'); 21 | }); 22 | } 23 | 24 | /** 25 | * Reverse the migrations. 26 | * 27 | * @return void 28 | */ 29 | public function down() 30 | { 31 | Schema::dropIfExists('user_roles'); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /resources/lang/en/agency.php: -------------------------------------------------------------------------------- 1 | 'Agency', 6 | 'not_found' => 'Agency not found', 7 | 'detail' => 'Agency Detail', 8 | 9 | // Actions 10 | 'edit' => 'Edit Agency', 11 | 'update' => 'Update Agency', 12 | 'updated' => 'Agency data has been updated.', 13 | 'logo_change' => 'Change Agency Logo', 14 | 'logo_upload' => 'Upload Agency Logo', 15 | 'logo_upload_info' => 'Upload a .png file with 200px width', 16 | 17 | // Attributes 18 | 'name' => 'Agency Name', 19 | 'tagline' => 'Agency Tagline', 20 | 'email' => 'Agency Email', 21 | 'website' => 'Agency Website', 22 | 'address' => 'Agency Address', 23 | 'phone' => 'Agency Phone', 24 | 'logo' => 'Agency Logo', 25 | 'tax_id' => 'Tax ID Number', 26 | ]; 27 | -------------------------------------------------------------------------------- /resources/lang/id/agency.php: -------------------------------------------------------------------------------- 1 | 'Agensi', 6 | 'not_found' => 'Agensi tidak ditemukan', 7 | 'detail' => 'Detail Agensi', 8 | 9 | // Actions 10 | 'edit' => 'Edit Agensi', 11 | 'update' => 'Update Agensi', 12 | 'updated' => 'Update data Agensi telah berhasil.', 13 | 'logo_change' => 'Ganti Logo Agensi', 14 | 'logo_upload' => 'Upload Logo Agensi', 15 | 'logo_upload_info' => 'Upload file .png dengan Lebar 200px', 16 | 17 | // Attributes 18 | 'name' => 'Nama Agensi', 19 | 'tagline' => 'Tagline Agensi', 20 | 'email' => 'Email Agensi', 21 | 'website' => 'Website Agensi', 22 | 'address' => 'Alamat Agensi', 23 | 'phone' => 'Telp. Agensi', 24 | 'logo' => 'Logo Agensi', 25 | 'tax_id' => 'NPWP', 26 | ]; 27 | -------------------------------------------------------------------------------- /resources/views/users/partials/nav-tabs.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 21 |
    22 | -------------------------------------------------------------------------------- /resources/lang/de/activity.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'project_created' => 'Project created: :name new :user.', 6 | 'project_updated' => 'Project data :name updated by :user.', 7 | 'job_deleted' => 'Job deleted by :user.', 8 | ], 9 | 'jobs' => [ 10 | 'job_created' => 'Job created: :name new :user.', 11 | 'job_updated' => 'Job data :name updated by :user.', 12 | 'task_deleted' => 'Task deleted by :user.', 13 | ], 14 | 'tasks' => [ 15 | 'task_created' => 'Task created: :name new :user.', 16 | 'task_updated' => 'Task data :name updated by :user.', 17 | ], 18 | ]; 19 | -------------------------------------------------------------------------------- /resources/lang/en/activity.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'project_created' => 'Project created: :name new :user.', 6 | 'project_updated' => 'Project data :name updated by :user.', 7 | 'job_deleted' => 'Job deleted by :user.', 8 | ], 9 | 'jobs' => [ 10 | 'job_created' => 'Job created: :name new :user.', 11 | 'job_updated' => 'Job data :name updated by :user.', 12 | 'task_deleted' => 'Task deleted by :user.', 13 | ], 14 | 'tasks' => [ 15 | 'task_created' => 'Task created: :name new :user.', 16 | 'task_updated' => 'Task data :name updated by :user.', 17 | ], 18 | ]; 19 | -------------------------------------------------------------------------------- /app/Entities/Payments/Payment.php: -------------------------------------------------------------------------------- 1 | belongsTo(Project::class); 19 | } 20 | 21 | public function partner() 22 | { 23 | return $this->morphTo(); 24 | } 25 | 26 | public function type() 27 | { 28 | $type = Type::getNameById($this->type_id); 29 | 30 | if ($this->in_out == 0 && $this->partner_type == 'App\Entities\Users\User') { 31 | $type .= ' Fee'; 32 | } 33 | 34 | return $type; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Listeners/Projects/LogProjectJobDeletionActivity.php: -------------------------------------------------------------------------------- 1 | job; 13 | $projectId = $job->project_id; 14 | 15 | $activityEntry = [ 16 | 'type' => 'job_deleted', 17 | 'parent_id' => null, 18 | 'user_id' => auth()->id(), 19 | 'object_id' => $projectId, 20 | 'object_type' => 'projects', 21 | 'data' => [ 22 | 'name' => $job->name, 23 | 'description' => $job->description, 24 | 'price' => $job->price, 25 | ], 26 | ]; 27 | 28 | Activity::create($activityEntry); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/Entities/Partners/Vendor.php: -------------------------------------------------------------------------------- 1 | morphMany('App\Entities\Payments\Payment', 'partner')->orderBy('date'); 24 | } 25 | 26 | /** 27 | * Get status attribute. 28 | * 29 | * @return string 30 | */ 31 | public function getStatusAttribute() 32 | { 33 | return $this->is_active == 1 ? __('app.active') : __('app.in_active'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/lang/id/activity.php: -------------------------------------------------------------------------------- 1 | [ 5 | 'project_created' => 'Input project baru: :name oleh :user.', 6 | 'project_updated' => 'Data project :name diubah oleh :user.', 7 | 'job_deleted' => 'Job dihapus oleh :user.', 8 | ], 9 | 'jobs' => [ 10 | 'job_created' => 'Input job baru: :name oleh :user.', 11 | 'job_updated' => 'Data job :name diubah oleh :user.', 12 | 'task_deleted' => 'Task dihapus oleh :user.', 13 | ], 14 | 'tasks' => [ 15 | 'task_created' => 'Input task baru: :name oleh :user.', 16 | 'task_updated' => 'Data task :name diubah oleh :user.', 17 | ], 18 | ]; 19 | -------------------------------------------------------------------------------- /app/Http/Requests/Tasks/UpdateRequest.php: -------------------------------------------------------------------------------- 1 | user()->can( 17 | 'update', $this->route('task') 18 | ); 19 | } 20 | 21 | /** 22 | * Get the validation rules that apply to the request. 23 | * 24 | * @return array 25 | */ 26 | public function rules() 27 | { 28 | return [ 29 | 'name' => 'required|max:60', 30 | 'description' => 'nullable|max:255', 31 | 'progress' => 'required|numeric|max:100', 32 | 'job_id' => 'required|numeric|exists:jobs,id', 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/views/auth/login.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.guest') 2 | 3 | @section('title', __('auth.login')) 4 | 5 | @section('content') 6 | 7 |
    8 | {!! app_logo_image() !!} 9 |

    {{ config('app.name') }}

    10 |
    11 |
    12 | {{ Form::open(['route' => 'auth.login']) }} 13 | {!! FormField::email('email', ['label' => false, 'placeholder'=> __('auth.email')]) !!} 14 | {!! FormField::password('password', ['label' => false, 'placeholder'=> __('auth.password')]) !!} 15 | {{ Form::submit(__('auth.login'), ['class' => 'btn btn-success btn-block']) }} 16 | {{ link_to_route('auth.reset-request', __('auth.forgot_password'), [], ['class' => 'btn btn-link']) }} 17 | {{ Form::close() }} 18 |
    19 |
    20 |
    21 | @endsection 22 | -------------------------------------------------------------------------------- /resources/lang/de/agency.php: -------------------------------------------------------------------------------- 1 | 'Agentur', 6 | 'not_found' => 'Agentur nicht gefunden', 7 | 'detail' => 'Agentur Detail', 8 | 9 | // Actions 10 | 'edit' => 'Agentur bearbeiten', 11 | 'update' => 'Agentur aktualisieren', 12 | 'updated' => 'Agentur wurde aktualisiert.', 13 | 'logo_change' => 'Agentur Logo ändern', 14 | 'logo_upload' => 'Upload Agentur Logo', 15 | 'logo_upload_info' => 'Lade eine .png Datei mit 200px Breite hoch', 16 | 17 | // Attributes 18 | 'name' => 'Agentur Name', 19 | 'tagline' => 'Agentur Tagline', 20 | 'email' => 'Agentur E-Mail', 21 | 'website' => 'Agentur Website', 22 | 'address' => 'Agentur Adresse', 23 | 'phone' => 'Agentur Telefon', 24 | 'logo' => 'Agentur Logo', 25 | 'tax_id' => 'Tax ID Number', 26 | ]; 27 | -------------------------------------------------------------------------------- /app/Entities/Projects/IssueStatus.php: -------------------------------------------------------------------------------- 1 | 'open', 11 | 1 => 'resolved', 12 | 2 => 'closed', 13 | 3 => 'on_hold', 14 | 4 => 'invalid', 15 | ]; 16 | 17 | protected static $colors = [ 18 | 0 => 'yellow', 19 | 1 => 'green', 20 | 2 => 'primary', 21 | 3 => 'default', 22 | 4 => 'warning', 23 | ]; 24 | 25 | public static function getNameById($singleId) 26 | { 27 | return __('issue.'.static::getById($singleId)); 28 | } 29 | 30 | public static function toArray() 31 | { 32 | $lists = []; 33 | foreach (static::$lists as $key => $value) { 34 | $lists[$key] = __('issue.'.$value); 35 | } 36 | 37 | return $lists; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwords must be at least six characters and match the confirmation.', 17 | 'user' => "We can't find a user with that e-mail address.", 18 | 'token' => 'This password reset token is invalid.', 19 | 'sent' => 'We have e-mailed your password reset link!', 20 | 'reset' => 'Your password has been reset!', 21 | 'back_to_login' => 'Back to Login', 22 | ]; 23 | -------------------------------------------------------------------------------- /database/migrations/2017_11_01_185745_create_vendors_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name', 60); 19 | $table->string('website')->nullable(); 20 | $table->boolean('is_active')->default(1); 21 | $table->string('notes')->nullable(); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('vendors'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /database/migrations/2018_08_04_110400_create_comments_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('commentable_type'); 19 | $table->unsignedInteger('commentable_id'); 20 | $table->string('body'); 21 | $table->unsignedInteger('creator_id'); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::dropIfExists('comments'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/email.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.guest') 2 | 3 | @section('title', __('auth.reset_password')) 4 | 5 | @section('content') 6 |
    7 |
    8 |

    {{ __('auth.reset_password') }}

    9 |
    10 | @if (session('status')) 11 |
    12 | {{ session('status') }} 13 |
    14 | @endif 15 | {!! Form::open(['route'=>'auth.reset-email']) !!} 16 | {!! FormField::email('email') !!} 17 | {!! Form::submit(__('auth.send_reset_password_link'), ['class'=>'btn btn-success btn-block']) !!} 18 | {!! link_to_route('auth.login', __('passwords.back_to_login'), [], ['class'=>'btn btn-default btn-block']) !!} 19 | {!! Form::close() !!} 20 |
    21 |
    22 |
    23 | @endsection 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/References/SiteOptionsController.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class SiteOptionsController extends Controller 15 | { 16 | public function page1() 17 | { 18 | return view('options.page-1'); 19 | } 20 | 21 | public function save1(Request $request) 22 | { 23 | $optionData = $request->validate([ 24 | 'money_sign' => 'required|max:3', 25 | 'money_sign_in_word' => 'required|max:15', 26 | ]); 27 | 28 | Option::set('money_sign', $optionData['money_sign']); 29 | Option::set('money_sign_in_word', $optionData['money_sign_in_word']); 30 | 31 | flash(__('option.updated'), 'success'); 32 | 33 | return redirect()->route('site-options.page-1'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /public/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/Http/Controllers/Auth/ForgotPasswordController.php: -------------------------------------------------------------------------------- 1 | middleware('guest'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->string('name'); 18 | $table->string('email')->unique(); 19 | $table->string('password', 60); 20 | $table->rememberToken(); 21 | $table->string('api_token')->nullable(); 22 | $table->char('lang', 2)->default('en'); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::drop('users'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /database/migrations/2016_07_09_142833_create_tasks_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->integer('job_id')->unsigned(); 18 | $table->string('name', 60); 19 | $table->string('description')->nullable(); 20 | $table->unsignedTinyInteger('progress')->default(0); 21 | $table->unsignedTinyInteger('position')->default(0); 22 | $table->timestamps(); 23 | }); 24 | } 25 | 26 | /** 27 | * Reverse the migrations. 28 | * 29 | * @return void 30 | */ 31 | public function down() 32 | { 33 | Schema::drop('tasks'); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/Http/Requests/Jobs/UpdateRequest.php: -------------------------------------------------------------------------------- 1 | get('project_id')); 18 | 19 | return auth()->user()->can('manage_jobs', $project); 20 | } 21 | 22 | /** 23 | * Get the validation rules that apply to the request. 24 | * 25 | * @return array 26 | */ 27 | public function rules() 28 | { 29 | return [ 30 | 'name' => 'required|max:60', 31 | 'price' => 'required|numeric', 32 | 'worker_id' => 'required|numeric', 33 | 'type_id' => 'required|numeric', 34 | 'description' => 'max:255', 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/views/jobs/partials/job-show.blade.php: -------------------------------------------------------------------------------- 1 |
    2 |

    {{ __('job.detail') }}

    3 | 4 | 5 | 6 | 7 | @can('see-pricings', $job) 8 | 9 | @endcan 10 | 11 | 12 | 13 | 14 | 15 |
    {{ __('job.name') }}{{ $job->name }}
    {{ __('job.type') }}{{ $job->type() }}
    {{ __('job.price') }}{{ format_money($job->price) }}
    {{ __('job.progress') }}{{ format_decimal($job->progress) }}%
    {{ __('job.worker') }}{{ $job->worker->name }}
    {{ __('time.updated_at') }}{{ $job->updated_at }}
    {{ __('job.description') }}{!! nl2br($job->description) !!}
    16 |
    17 | -------------------------------------------------------------------------------- /resources/views/subscriptions/partials/delete.blade.php: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |

    {{ __('subscription.delete') }}

    5 | @include('subscriptions.partials.subscription-show') 6 |
    7 | {{ __('app.delete_confirm') }} 8 |
    9 | 18 |
    19 |
    20 |
    21 | -------------------------------------------------------------------------------- /database/factories/ProjectFactory.php: -------------------------------------------------------------------------------- 1 | define(Project::class, function (Faker $faker) { 8 | $proposalDate = $faker->dateTimeBetween('-1 year', '-1 month')->format('Y-m-d'); 9 | $startDate = Carbon::parse($proposalDate)->addDays(10); 10 | $endDate = $startDate->addDays(rand(1, 13) * 7); 11 | 12 | return [ 13 | 'name' => $faker->sentence(3), 14 | 'description' => $faker->paragraph, 15 | 'proposal_date' => $proposalDate, 16 | 'start_date' => $startDate->format('Y-m-d'), 17 | 'end_date' => $endDate->format('Y-m-d'), 18 | 'project_value' => $projectValue = rand(1, 10) * 500000, 19 | 'proposal_value' => $projectValue, 20 | 'status_id' => rand(1, 6), 21 | 'customer_id' => function () { 22 | return factory(Customer::class)->create()->id; 23 | }, 24 | ]; 25 | }); 26 | -------------------------------------------------------------------------------- /resources/lang/de/passwords.php: -------------------------------------------------------------------------------- 1 | 'Passwörter müssen mindestens sechs Zeichen lang sein und der Bestätigung entsprechen.', 17 | 'user' => 'Wir können keinen Benutzer mit dieser E-Mailadresse finden.', 18 | 'token' => 'Dieses Passwort Reset Token ist ungültig.', 19 | 'sent' => 'Wir haben Ihnen Ihr Passwort Rest Link per E-Mail zugesandt!', 20 | 'reset' => 'Ihr Passwort wurde zurückgesetzt!', 21 | 'back_to_login' => 'Zurück zum Login', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/views/invoices/partials/detail.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
    {{ __('invoice.number') }}{{ $invoice->number }}
    {{ __('invoice.date') }}{{ $invoice->date }}
    {{ __('invoice.due_date') }}{{ $invoice->due_date }}
    {{ __('invoice.project') }}{{ $invoice->project->nameLink() }}
    {{ __('invoice.customer') }}{{ $invoice->project->customer->nameLink() }}
    {{ __('invoice.items_count') }}{{ $invoice->items_count }}
    {{ __('invoice.creator') }}{{ $invoice->creator->name }}
    {{ __('invoice.amount') }}{{ format_money($invoice->amount) }}
    {{ __('invoice.notes') }}{{ $invoice->notes }}
    14 | -------------------------------------------------------------------------------- /public/assets/js/sb-admin-2.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#side-menu').metisMenu(); 4 | 5 | }); 6 | 7 | //Loads the correct sidebar on window load, 8 | //collapses the sidebar on window resize. 9 | // Sets the min-height of #page-wrapper to window size 10 | $(function() { 11 | $(window).bind("load resize", function() { 12 | topOffset = 50; 13 | width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width; 14 | if (width < 768) { 15 | $('div.navbar-collapse').addClass('collapse') 16 | topOffset = 100; // 2-row-menu 17 | } else { 18 | $('div.navbar-collapse').removeClass('collapse') 19 | } 20 | 21 | // height = (this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height; 22 | // height = height - topOffset; 23 | // if (height < 1) height = 1; 24 | // if (height > topOffset) { 25 | // $("#page-wrapper").css("min-height", (height) + "px"); 26 | // } 27 | }) 28 | }); 29 | -------------------------------------------------------------------------------- /resources/lang/en/task.php: -------------------------------------------------------------------------------- 1 | 'Task', 6 | 'list' => 'Task List', 7 | 'empty' => 'Task List is empty.', 8 | 'search' => 'Search Task', 9 | 'found' => 'Task found.', 10 | 'not_found' => 'Task not found.', 11 | 'back_to_index' => 'Back to Task List', 12 | 'move_to_other_job' => 'Move to other Job', 13 | 14 | // Actions 15 | 'create' => 'Create new Task', 16 | 'created' => 'Task has been created.', 17 | 'show' => 'Task Detail', 18 | 'edit' => 'Edit Task', 19 | 'update' => 'Update Task', 20 | 'updated' => 'Task has been updated.', 21 | 'delete' => 'Delete Task', 22 | 'deleted' => 'Task has been deleted.', 23 | 'undeleted' => 'Task not deleted.', 24 | 'set_done' => 'Set done', 25 | 26 | // Attributes 27 | 'name' => 'Task Name', 28 | 'progress' => 'Progress', 29 | 'description' => 'Task Description', 30 | ]; 31 | -------------------------------------------------------------------------------- /resources/views/layouts/dashboard.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('content') 4 |
    5 | {!! Form::open(['route' => 'projects.index', 'method' => 'get', 'class' => 'form-inline']) !!} 6 | {!! Form::text('q', null, [ 7 | 'class' => 'form-control index-search-field', 8 | 'placeholder' => __('project.search'), 9 | 'style' => 'width:100%;max-width:350px' 10 | ]) !!} 11 | {!! Form::submit(__('project.search'), ['class' => 'btn btn-info btn-sm']) !!} 12 | @can('create', new App\Entities\Projects\Project) 13 | {{ link_to_route('projects.create', __('project.create'), [], [ 14 | 'class' => 'btn btn-success pull-right', 15 | 'style' => 'margin: -2px 0px;' 16 | ]) }} 17 | @endcan 18 | {!! Form::close() !!} 19 |
    20 | 21 | @include('pages.partials.dashboard-nav-tabs') 22 | 23 | @yield('content-dashboard') 24 | 25 | @endsection 26 | -------------------------------------------------------------------------------- /app/Http/Requests/Accounts/RegisterRequest.php: -------------------------------------------------------------------------------- 1 | guest(); 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 | 'agency_name' => 'required|max:255', 28 | 'agency_website' => 'nullable|url|max:255', 29 | 'name' => 'required|max:255', 30 | 'email' => 'required|email|max:255|unique:users,email', 31 | 'password' => 'required|between:6,15|confirmed', 32 | 'password_confirmation' => 'required', 33 | ]; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/lang/id/passwords.php: -------------------------------------------------------------------------------- 1 | 'Password harus minimal enam karakter dan cocok dengan konfirmasi.', 17 | 'user' => 'Kami tidak dapat menemukan pengguna dengan email tersebut.', 18 | 'token' => 'Token Reset Password tidak sah.', 19 | 'sent' => 'Kami sudah mengirim email yang berisi tautan untuk mereset Password Anda!', 20 | 'reset' => 'Password Anda sudah direset!', 21 | 'back_to_login' => 'Kembali ke Login', 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/views/users/activities/jobs/job_updated.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 |

    7 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 8 | 'user' => $activity->user->name, 9 | 'name' => $activity->object->name, 10 | ]) !!} 11 |

    12 | @php 13 | $data = $activity->data; 14 | @endphp 15 | @foreach ($data['before'] as $key => $value) 16 | @php 17 | if (in_array($key, ['price']) && !is_null($value)) { 18 | $value = format_money($value); 19 | } 20 | $afterValue = $data['after'][$key] ?? null; 21 | if (in_array($key, ['price']) && !is_null($afterValue)) { 22 | $afterValue = format_money($afterValue); 23 | } 24 | @endphp 25 |
    {{ __('job.'.$key) }}: {{ $value }} => {{ $afterValue }}
    26 | @endforeach 27 | @endslot 28 | @endcomponent 29 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/reset.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.guest') 2 | 3 | @section('title', __('auth.reset_password')) 4 | 5 | @section('content') 6 |
    7 |
    8 |

    {{ __('auth.reset_password') }}

    9 | {!! Form::open(['route' => 'reset-password']) !!} 10 |
    11 |

    {{ __('auth.reset_password_hint') }} :

    12 | {!! FormField::email('email') !!} 13 | {!! FormField::password('password', ['label' => __('auth.new_password')]) !!} 14 | {!! FormField::password('password_confirmation', ['label' => __('auth.new_password_confirmation')]) !!} 15 | {!! Form::hidden('token', $token) !!} 16 |
    17 | 20 | {!! Form::close() !!} 21 |
    22 |
    23 | @endsection 24 | -------------------------------------------------------------------------------- /database/migrations/2018_10_30_215937_create_bank_accounts_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name', 60); 19 | $table->string('number', 30); 20 | $table->string('account_name', 60); 21 | $table->string('description')->nullable(); 22 | $table->boolean('is_active')->default(1); // 1:active, 0:in_active 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('bank_accounts'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Http/Requests/Payments/UpdateRequest.php: -------------------------------------------------------------------------------- 1 | user()->can('manage_payments'); 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 | 'date' => 'required|date|date_format:Y-m-d', 28 | 'in_out' => 'required|numeric', 29 | 'amount' => 'required', 30 | 'project_id' => 'required|numeric', 31 | 'type_id' => 'required|numeric', 32 | 'partner_type' => 'nullable|string', 33 | 'partner_id' => 'required|numeric', 34 | 'description' => 'required|max:255', 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/views/users/activities/projects/project_updated.blade.php: -------------------------------------------------------------------------------- 1 | @component('users.activities.activity_list_item') 2 | @slot('time') 3 | {{ $activity->created_at }} 4 | @endslot 5 | @slot('body') 6 |

    7 | {!! __('activity.'.$activity->object_type.'.'.$activity->type, [ 8 | 'user' => $activity->user->name, 9 | 'name' => $activity->object->name, 10 | ]) !!} 11 |

    12 | @php 13 | $data = $activity->data; 14 | @endphp 15 | @foreach ($data['before'] as $key => $value) 16 | @php 17 | $afterValue = $data['after'][$key] ?? null; 18 | @endphp 19 |
    20 | @if ($key == 'status_id') 21 | {{ __('project.status') }}: 22 | {{ App\Entities\Projects\Status::getNameById($value) }} 23 | => {{ App\Entities\Projects\Status::getNameById($afterValue) }} 24 | @else 25 | {{ __('project.'.$key) }}: {{ $value }} => {{ $afterValue }} 26 | @endif 27 |
    28 | @endforeach 29 | @endslot 30 | @endcomponent 31 | -------------------------------------------------------------------------------- /app/Http/Requests/Partners/CustomerCreateRequest.php: -------------------------------------------------------------------------------- 1 | user()->can('create', new Customer); 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|max:60', 29 | 'email' => 'nullable|email|unique:customers,email', 30 | 'phone' => 'nullable|max:255', 31 | 'pic' => 'nullable|max:255', 32 | 'address' => 'nullable|max:255', 33 | 'website' => 'nullable|url|max:255', 34 | 'notes' => 'nullable|max:255', 35 | ]; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2017_08_03_235706_create_files_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->unsignedInteger('fileable_id'); 19 | $table->string('fileable_type', 60); 20 | $table->tinyInteger('type_id')->unsigned()->nullable(); 21 | $table->string('filename', 60); 22 | $table->string('title', 60); 23 | $table->string('description')->nullable(); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('files'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/lang/de/report.php: -------------------------------------------------------------------------------- 1 | 'Report', 6 | 'sales' => 'Earning Report', 7 | 'view_report' => 'View Report', 8 | 'sales_graph' => 'Earning Graph', 9 | 'detail' => 'Report Detail', 10 | 'profit' => 'Profit', 11 | 12 | // Daily 13 | 'daily' => 'Daily Report : :date', 14 | 'today' => 'Today', 15 | 'view_daily' => 'View Daily', 16 | 'view_daily_label' => 'View Daily per', 17 | 18 | // Monthly 19 | 'monthly' => 'Monthly Report :year_month', 20 | 'this_month' => 'This Month', 21 | 'view_monthly' => 'View Monthly', 22 | 'view_monthly_label' => 'View Monthly per', 23 | 24 | // Yearly 25 | 'yearly' => 'Yearly Report :year', 26 | 'this_year' => 'This Year', 27 | 'view_yearly' => 'View Yearly', 28 | 'view_yearly_label' => 'View Report per', 29 | 30 | // Year to year 31 | 'year_to_year' => 'Year to Year Report', 32 | 'view_year_to_year' => 'View Year to Year Report', 33 | ]; 34 | -------------------------------------------------------------------------------- /resources/lang/en/report.php: -------------------------------------------------------------------------------- 1 | 'Report', 6 | 'sales' => 'Earning Report', 7 | 'view_report' => 'View Report', 8 | 'sales_graph' => 'Earning Graph', 9 | 'detail' => 'Report Detail', 10 | 'profit' => 'Profit', 11 | 12 | // Daily 13 | 'daily' => 'Daily Report : :date', 14 | 'today' => 'Today', 15 | 'view_daily' => 'View Daily', 16 | 'view_daily_label' => 'View Daily per', 17 | 18 | // Monthly 19 | 'monthly' => 'Monthly Report :year_month', 20 | 'this_month' => 'This Month', 21 | 'view_monthly' => 'View Monthly', 22 | 'view_monthly_label' => 'View Monthly per', 23 | 24 | // Yearly 25 | 'yearly' => 'Yearly Report :year', 26 | 'this_year' => 'This Year', 27 | 'view_yearly' => 'View Yearly', 28 | 'view_yearly_label' => 'View Report per', 29 | 30 | // Year to year 31 | 'year_to_year' => 'Year to Year Report', 32 | 'view_year_to_year' => 'View Year to Year Report', 33 | ]; 34 | -------------------------------------------------------------------------------- /tests/Unit/Models/CommentTest.php: -------------------------------------------------------------------------------- 1 | make(); 18 | 19 | $this->assertInstanceOf(User::class, $comment->creator); 20 | $this->assertEquals($comment->creator_id, $comment->creator->id); 21 | } 22 | 23 | /** @test */ 24 | public function a_comment_has_time_display_attribute() 25 | { 26 | $comment = factory(Comment::class)->create(['created_at' => now()->subHour()]); 27 | $this->assertEquals($comment->created_at->diffForHumans(), $comment->time_display); 28 | 29 | $comment = factory(Comment::class)->create(['created_at' => now()->subDays(3)]); 30 | $this->assertEquals($comment->created_at, $comment->time_display); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 6 | "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", 7 | "watch-poll": "npm run watch -- --watch-poll", 8 | "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", 9 | "prod": "npm run production", 10 | "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.15.3", 14 | "bootstrap-sass": "^3.4.1", 15 | "cross-env": "^3.2.3", 16 | "jquery": "^3.1.1", 17 | "laravel-mix": "0.*", 18 | "lodash": "^4.17.13" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /routes/web/references.php: -------------------------------------------------------------------------------- 1 | 'References', 'middleware' => ['web', 'role:admin']], function () { 4 | /* 5 | * Options Routes 6 | */ 7 | Route::get('options', ['as' => 'options.index', 'uses' => 'OptionsController@index']); 8 | Route::post('options/store', ['as' => 'options.store', 'uses' => 'OptionsController@store']); 9 | Route::patch('options/save', ['as' => 'options.save', 'uses' => 'OptionsController@save']); 10 | Route::delete('options/{optionId}/destroy', ['as' => 'options.destroy', 'uses' => 'OptionsController@destroy']); 11 | 12 | /* 13 | * Site Options Routes 14 | */ 15 | Route::get('site-options', ['as' => 'site-options.page-1', 'uses' => 'SiteOptionsController@page1']); 16 | Route::patch('site-options/save-1', ['as' => 'site-options.save-1', 'uses' => 'SiteOptionsController@save1']); 17 | 18 | /* 19 | * Bank Accounts Routes 20 | */ 21 | Route::apiResource('bank-accounts', 'BankAccountsController'); 22 | Route::post('bank-accounts/import', 'BankAccountsController@import')->name('bank-accounts.import'); 23 | }); 24 | -------------------------------------------------------------------------------- /database/migrations/2016_11_25_145359_create_user_events_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->integer('user_id')->unsigned(); 18 | $table->integer('project_id')->unsigned()->nullable(); 19 | $table->string('title', 60); 20 | $table->string('body')->nullable(); 21 | $table->dateTime('start')->nullable(); 22 | $table->dateTime('end')->nullable(); 23 | $table->boolean('is_allday')->default(0); 24 | $table->timestamps(); 25 | }); 26 | } 27 | 28 | /** 29 | * Reverse the migrations. 30 | * 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::drop('user_events'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/views/payments/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', __('payment.detail')) 4 | 5 | @section('content') 6 | 7 | @include('payments.partials.breadcrumb') 8 | 9 |
    10 |
    11 | {{ __('payment.detail') }} {{ __('app.type') }} : {{ $payment->type() }} 12 | @include('payments.partials.payment-show') 13 |
    14 |
    15 | {{ __('app.action') }} 16 |

    {!! link_to_route('payments.pdf', __('payment.print'), [$payment->id], ['class' => 'btn btn-success']) !!}

    17 |

    {!! link_to_route('payments.edit', __('payment.edit'), [$payment->id], ['class' => 'btn btn-warning']) !!}

    18 |

    {!! link_to_route('projects.payments', __('project.view_payments'), [$payment->project_id], ['class' => 'btn btn-default']) !!}

    19 |

    {!! link_to_route('payments.index', __('payment.back_to_index'), [], ['class' => 'btn btn-default']) !!}

    20 |
    21 |
    22 | @endsection 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Nafies Luthfi 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. -------------------------------------------------------------------------------- /app/Entities/Users/UserRole.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class UserRole extends Model 13 | { 14 | /** 15 | * The table associated with the model. 16 | * 17 | * @var string 18 | */ 19 | protected $table = 'user_roles'; 20 | 21 | /** 22 | * Indicates if the model should be timestamped. 23 | * 24 | * @var bool 25 | */ 26 | public $timestamps = false; 27 | 28 | /** 29 | * The accessors to append to the model's array form. 30 | * 31 | * @var array 32 | */ 33 | protected $appends = ['name']; 34 | 35 | /** 36 | * The attributes that are mass assignable. 37 | * 38 | * @var array 39 | */ 40 | protected $fillable = ['user_id', 'role_id']; 41 | 42 | /** 43 | * Role name attribute. 44 | * 45 | * @return string 46 | */ 47 | public function getNameAttribute() 48 | { 49 | return Role::getNameById($this->role_id); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /config/compile.php: -------------------------------------------------------------------------------- 1 | [ 17 | // 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled File Providers 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may list service providers which define a "compiles" function 26 | | that returns additional files that should be compiled, providing an 27 | | easy way to get common files from any packages you are utilizing. 28 | | 29 | */ 30 | 31 | 'providers' => [ 32 | // 33 | ], 34 | 35 | ]; 36 | -------------------------------------------------------------------------------- /resources/lang/id/report.php: -------------------------------------------------------------------------------- 1 | 'Laporan', 6 | 'sales' => 'Laponan Penjualan', 7 | 'view_report' => 'Lihat Laporan', 8 | 'sales_graph' => 'Grafik Penjualan', 9 | 'detail' => 'Detail Laporan', 10 | 'profit' => 'Profit', 11 | 12 | // Daily 13 | 'daily' => 'Laponan Harian: :date', 14 | 'today' => 'Hari Ini', 15 | 'view_daily' => 'Lihat Harian', 16 | 'view_daily_label' => 'Lihat Harian per', 17 | 18 | // Monthly 19 | 'monthly' => 'Laponan Bulan :year_month', 20 | 'this_month' => 'Bulan Ini', 21 | 'view_monthly' => 'Lihat Bulanan', 22 | 'view_monthly_label' => 'Lihat Bulanan per', 23 | 24 | // Yearly 25 | 'yearly' => 'Laponan Tahun :year', 26 | 'this_year' => 'Tahun Ini', 27 | 'view_yearly' => 'Lihat Tahunan', 28 | 'view_yearly_label' => 'Lihat Tahunan per', 29 | 30 | // Year to year 31 | 'year_to_year' => 'Laponan Tahun ke Tahun', 32 | 'view_year_to_year' => 'Lihat Laporan Tahun ke Tahun', 33 | ]; 34 | -------------------------------------------------------------------------------- /resources/views/view-components/dashboard-panel.blade.php: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 |
    12 |
    13 |
    14 |
    15 |
    16 |
    {{ $number }}
    17 |
    {{ $text }}
    18 |
    19 |
    20 |
    21 | 24 |
    25 |
    26 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | 'v1', 'namespace' => 'Api', 'as' => 'api.', 'middleware' => ['auth:api']], function () { 4 | require __DIR__.'/api/projects.php'; 5 | /* 6 | * Calendar 7 | */ 8 | Route::get('get-events', ['as' => 'events.index', 'uses' => 'EventsController@index']); 9 | Route::post('events', ['as' => 'events.store', 'uses' => 'EventsController@store']); 10 | Route::patch('events/update', ['as' => 'events.update', 'uses' => 'EventsController@update']); 11 | Route::patch('events/reschedule', ['as' => 'events.reschedule', 'uses' => 'EventsController@reschedule']); 12 | Route::delete('events/delete', ['as' => 'events.destroy', 'uses' => 'EventsController@destroy']); 13 | Route::get('events/subscriptions', ['as' => 'events.subscriptions.index', 'uses' => 'SubscriptionEventController@index']); 14 | 15 | /* 16 | * Customer Route 17 | */ 18 | Route::post('customers', 'CustomerController@index')->name('customers.index'); 19 | 20 | /* 21 | * Vendor Route 22 | */ 23 | Route::post('vendors', 'VendorController@index')->name('vendors.index'); 24 | }); 25 | -------------------------------------------------------------------------------- /resources/lang/de/task.php: -------------------------------------------------------------------------------- 1 | 'Vorgang', 6 | 'list' => 'Vorgangsliste', 7 | 'empty' => 'Vorgangsliste ist leer.', 8 | 'search' => 'Vorgang ', 9 | 'found' => 'Vorgang gefunden.', 10 | 'not_found' => 'Vorgang nicht gefunden.', 11 | 'back_to_index' => 'Zurück zur Vorgangsliste', 12 | 'move_to_other_job' => 'Zu einer anderen Beschäftigung verschieben', 13 | 14 | // Actions 15 | 'create' => 'Neuen Vorgang erstellen', 16 | 'created' => 'Vorgang wurde erstellt.', 17 | 'show' => 'Vorgangsdetails', 18 | 'edit' => 'Vorgang bearbeiten', 19 | 'update' => 'Vorgang aktualisieren', 20 | 'updated' => 'Vorgang wurde aktualisiert.', 21 | 'delete' => 'Vorgang löschen', 22 | 'deleted' => 'Vorgan wurde gelöscht.', 23 | 'undeleted' => 'Vorgang nicht gelöscht.', 24 | 'set_done' => 'Set done', 25 | 26 | // Attributes 27 | 'name' => 'Vorgang Name', 28 | 'progress' => 'Fortschritt', 29 | 'description' => 'Vorgang Beschreibung', 30 | ]; 31 | -------------------------------------------------------------------------------- /config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | ], 21 | 22 | 'mandrill' => [ 23 | 'secret' => env('MANDRILL_SECRET'), 24 | ], 25 | 26 | 'ses' => [ 27 | 'key' => env('SES_KEY'), 28 | 'secret' => env('SES_SECRET'), 29 | 'region' => 'us-east-1', 30 | ], 31 | 32 | 'stripe' => [ 33 | 'model' => App\User::class, 34 | 'key' => env('STRIPE_KEY'), 35 | 'secret' => env('STRIPE_SECRET'), 36 | ], 37 | 38 | ]; 39 | -------------------------------------------------------------------------------- /resources/views/layouts/guest.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | @yield('title', config('app.name')) 11 | 12 | {!! Html::style('assets/css/app.css') !!} 13 | @yield('ext_css') 14 | 15 | 16 |
    17 |
    18 | @yield('content') 19 |
    20 | @include('layouts.partials.footer') 21 |
    22 | 23 | {!! Html::script(url('assets/js/jquery.js')) !!} 24 | {!! Html::script(url('assets/js/bootstrap.min.js')) !!} 25 | @include('layouts.partials.noty') 26 | @yield('ext_js') 27 | 28 | 33 | 34 | @yield('script') 35 | 36 | 37 | -------------------------------------------------------------------------------- /resources/views/projects/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.project') 2 | 3 | @section('action-buttons') 4 | @can('update', $project) 5 | {!! link_to_route('projects.edit', __('project.edit'), $project, ['class' => 'btn btn-warning']) !!} 6 | @endcan 7 | {!! link_to_route('projects.index', __('project.back_to_index'), ['status_id' => $project->status_id], ['class' => 'btn btn-default']) !!} 8 | @endsection 9 | 10 | @section('content-project') 11 | 12 |
    13 |
    14 | @include('projects.partials.project-show') 15 |
    16 |
    17 | @can('update', $project) 18 | {!! Form::model($project, ['route' => ['projects.status-update', $project], 'method' => 'patch', 'class' => 'well well-sm form-inline']) !!} 19 | {!! FormField::select('status_id', ProjectStatus::toArray(), ['label' => __('project.status')]) !!} 20 | {!! Form::submit(__('project.update_status'), ['class' => 'btn btn-info btn-sm']) !!} 21 | {!! Form::close() !!} 22 | @endcan 23 | @include('projects.partials.project-stats') 24 |
    25 |
    26 | 27 | @endsection 28 | -------------------------------------------------------------------------------- /routes/web/reports.php: -------------------------------------------------------------------------------- 1 | ['web', 'role:admin'], 'prefix' => 'reports'], function () { 4 | /* 5 | * Reports Routes 6 | */ 7 | Route::get('payments', 'ReportsController@monthly')->name('reports.payments.index'); 8 | Route::get('payments/daily', 'ReportsController@daily')->name('reports.payments.daily'); 9 | Route::get('payments/monthly', 'ReportsController@monthly')->name('reports.payments.monthly'); 10 | Route::get('payments/yearly', 'ReportsController@yearly')->name('reports.payments.yearly'); 11 | Route::get('payments/year_to_year', 'ReportsController@yearToYear')->name('reports.payments.year_to_year'); 12 | Route::get('current-credits', 'ReportsController@currentCredits')->name('reports.current-credits'); 13 | 14 | /* 15 | * Log Files Routes 16 | */ 17 | Route::get('log-files', 'Reports\LogFileController@index')->name('log-files.index'); 18 | Route::get('log-files/{fileName}', 'Reports\LogFileController@show')->name('log-files.show'); 19 | Route::get('log-files/{fileName}/download', 'Reports\LogFileController@download')->name('log-files.download'); 20 | }); 21 | -------------------------------------------------------------------------------- /tests/Unit/Helpers/MoneyFormatTest.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class MoneyFormatTest extends TestCase 14 | { 15 | use RefreshDatabase; 16 | 17 | /** @test */ 18 | public function format_money_returns_string_with_default_money_sign() 19 | { 20 | $this->assertEquals('Rp. 1.000', format_money(1000)); 21 | $this->assertEquals('Rp. 0', format_money(0)); 22 | $this->assertEquals('- Rp. 1.000', format_money(-1000)); 23 | } 24 | 25 | /** @test */ 26 | public function format_money_returns_string_based_on_site_option_money_sign() 27 | { 28 | \DB::table('site_options')->insert([ 29 | 'key' => 'money_sign', 30 | 'value' => 'USD', 31 | ]); 32 | 33 | $this->assertEquals('USD 1.000', format_money(1000)); 34 | $this->assertEquals('USD 0', format_money(0)); 35 | $this->assertEquals('- USD 1.000', format_money(-1000)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | realpath(base_path('resources/views')), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => realpath(storage_path('framework/views')), 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /database/migrations/2019_03_03_210017_create_issues_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->unsignedInteger('project_id'); 19 | $table->string('title', 60); 20 | $table->string('body'); 21 | $table->unsignedInteger('creator_id'); 22 | $table->unsignedTinyInteger('priority_id'); 23 | $table->unsignedInteger('pic_id')->nullable(); 24 | $table->unsignedTinyInteger('status_id')->default(0); 25 | $table->timestamps(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('issues'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/views/invoice-drafts/partials/invoice-draft-tabs.blade.php: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /config/simple-crud.php: -------------------------------------------------------------------------------- 1 | 'layouts.app', 15 | 16 | /* 17 | |-------------------------------------------------------------------------- 18 | | Base Test Class Path 19 | |-------------------------------------------------------------------------- 20 | | 21 | | Base TestCase Path on Laravel application 22 | | 23 | */ 24 | 25 | 'base_test_path' => 'tests/TestCase.php', 26 | 27 | /* 28 | |-------------------------------------------------------------------------- 29 | | Base Test Class 30 | |-------------------------------------------------------------------------- 31 | | 32 | | Base Test Class that used on Laravel application 33 | | according to 'base_test_path' config above 34 | | 35 | */ 36 | 37 | 'base_test_class' => 'Tests\TestCase', 38 | 39 | ]; 40 | -------------------------------------------------------------------------------- /database/factories/SubscriptionFactory.php: -------------------------------------------------------------------------------- 1 | define(Subscription::class, function (Faker $faker) { 12 | $startDate = Carbon::parse($faker->dateTimeBetween('-1 year', '-1 month')->format('Y-m-d')); 13 | 14 | return [ 15 | 'project_id' => function () { 16 | return factory(Project::class)->create()->id; 17 | }, 18 | 'type_id' => 1, 19 | 'status_id' => 1, 20 | 'name' => 'www.'.Str::random(10).'.com', 21 | 'price' => 125000, 22 | 'start_date' => $startDate->format('Y-m-d'), 23 | 'due_date' => $startDate->addYears(1)->format('Y-m-d'), 24 | 'customer_id' => function () { 25 | return factory(Customer::class)->create()->id; 26 | }, 27 | 'vendor_id' => function () { 28 | return factory(Vendor::class)->create()->id; 29 | }, 30 | ]; 31 | }); 32 | -------------------------------------------------------------------------------- /tests/Feature/Api/Projects/ReorderTaskListTest.php: -------------------------------------------------------------------------------- 1 | adminUserSigningIn(); 18 | $job = factory(Project::class)->create(); 19 | $task1 = factory(Task::class)->create(['job_id' => $job->id, 'position' => 1]); 20 | $task2 = factory(Task::class)->create(['job_id' => $job->id, 'position' => 2]); 21 | 22 | $this->postJson(route('jobs.tasks-reorder', $job), [ 23 | 'postData' => $task2->id.','.$task1->id, 24 | ]); 25 | 26 | $this->seeInDatabase('tasks', [ 27 | 'id' => $task1->id, 28 | 'position' => 2, 29 | ]); 30 | 31 | $this->seeInDatabase('tasks', [ 32 | 'id' => $task2->id, 33 | 'position' => 1, 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /resources/views/users/profile/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.dashboard') 2 | 3 | @section('title', trans('auth.profile')) 4 | 5 | @section('content-dashboard') 6 |
    7 |
    8 |
    9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
    {{ trans('user.user_id') }}{{ $user->id }}
    {{ trans('user.name') }}{{ $user->name }}
    {{ trans('user.email') }}{{ $user->email }}
    {{ trans('user.role') }}{!! $user->roleList() !!}
    {{ trans('user.api_token') }}{{ $user->api_token }}
    {{ trans('lang.lang') }}{{ trans('lang.'.$user->lang) }}
    17 | 20 |
    21 |
    22 |
    23 | @endsection 24 | -------------------------------------------------------------------------------- /resources/lang/en/file.php: -------------------------------------------------------------------------------- 1 | 'File', 6 | 'list' => 'File List', 7 | 'search' => 'Search File', 8 | 'not_found' => 'File not found.', 9 | 'empty' => 'File list is empty.', 10 | 'back_to_index' => 'Back to File List', 11 | 12 | // Actions 13 | 'create' => 'Upload new File', 14 | 'created' => 'New File has been created.', 15 | 'edit' => 'Edit File', 16 | 'update' => 'Update File', 17 | 'updated' => 'New File has been updated.', 18 | 'delete' => 'Delete File', 19 | 'delete_confirm' => 'Are you sure to delete this File?', 20 | 'deleted' => 'File has been deleted.', 21 | 'undeleted' => 'File not deleted.', 22 | 'undeleteable' => 'File can not be deleted.', 23 | 'select' => 'Select File', 24 | 'upload' => 'Upload File', 25 | 'download' => 'Download', 26 | 27 | // Attributes 28 | 'title' => 'File Name', 29 | 'description' => 'File Description', 30 | 'size' => 'File Size', 31 | 'updated_at' => 'Udpated at', 32 | ]; 33 | -------------------------------------------------------------------------------- /tests/Feature/Api/Projects/ReorderJobListTest.php: -------------------------------------------------------------------------------- 1 | adminUserSigningIn(); 18 | $project = factory(Project::class)->create(); 19 | $job1 = factory(Job::class)->create(['project_id' => $project->id, 'position' => 1]); 20 | $job2 = factory(Job::class)->create(['project_id' => $project->id, 'position' => 2]); 21 | 22 | $this->postJson(route('projects.jobs-reorder', $project), [ 23 | 'postData' => $job2->id.','.$job1->id, 24 | ]); 25 | 26 | $this->seeInDatabase('jobs', [ 27 | 'id' => $job1->id, 28 | 'position' => 2, 29 | ]); 30 | 31 | $this->seeInDatabase('jobs', [ 32 | 'id' => $job2->id, 33 | 'position' => 1, 34 | ]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /app/Http/Requests/Jobs/CreateRequest.php: -------------------------------------------------------------------------------- 1 | segment(2)); 18 | 19 | return auth()->user()->can('manage_jobs', $project); 20 | } 21 | 22 | /** 23 | * Get the validation rules that apply to the request. 24 | * 25 | * @return array 26 | */ 27 | public function rules() 28 | { 29 | return [ 30 | 'name' => 'required|max:60', 31 | 'price' => 'required|numeric', 32 | 'worker_id' => 'required|numeric', 33 | 'type_id' => 'required|numeric', 34 | 'target_start_date' => 'nullable|date|date_format:Y-m-d', 35 | 'target_end_date' => 'nullable|date|date_format:Y-m-d', 36 | 'description' => 'max:255', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /app/Http/Controllers/Api/ProjectsController.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class ProjectsController extends Controller 15 | { 16 | private $repo; 17 | 18 | public function __construct(ProjectsRepository $repo) 19 | { 20 | $this->repo = $repo; 21 | } 22 | 23 | public function index(Request $request) 24 | { 25 | return $this->repo->getProjects($request->get('q'), $request->get('status_id'), auth()->user()); 26 | } 27 | 28 | public function show($id) 29 | { 30 | return $this->repo->requireById($id); 31 | } 32 | 33 | public function jobs($id) 34 | { 35 | $project = $this->repo->requireById($id); 36 | $response = fractal() 37 | ->item($project->toArray()) 38 | ->transformWith(function ($project) { 39 | return $project; 40 | }) 41 | ->toArray(); 42 | 43 | return $response; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/Entities/Projects/File.php: -------------------------------------------------------------------------------- 1 | morphTo(); 15 | } 16 | 17 | public function project() 18 | { 19 | return $this->morphTo('fileable', Project::class); 20 | } 21 | 22 | public function getSize() 23 | { 24 | return $this->fileExists() ? \Storage::size('public/files/'.$this->filename) : 0; 25 | } 26 | 27 | public function getDate() 28 | { 29 | return $this->updated_at->format('Y-m-d'); 30 | } 31 | 32 | public function getTime() 33 | { 34 | return $this->updated_at->format('H:i:s'); 35 | } 36 | 37 | public function fileExists() 38 | { 39 | return \Storage::exists('public/files/'.$this->filename); 40 | } 41 | 42 | public function delete() 43 | { 44 | Storage::delete('public/files/'.$this->filename); 45 | 46 | return parent::delete(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/Http/Requests/Partners/CustomerUpdateRequest.php: -------------------------------------------------------------------------------- 1 | user()->can('update', $this->route('customer')); 17 | } 18 | 19 | /** 20 | * Get the validation rules that apply to the request. 21 | * 22 | * @return array 23 | */ 24 | public function rules() 25 | { 26 | $customer = $this->route('customer'); 27 | 28 | return [ 29 | 'name' => 'required|max:60', 30 | 'email' => 'nullable|email|unique:customers,email,'.$customer->id, 31 | 'phone' => 'nullable|max:255', 32 | 'pic' => 'nullable|max:255', 33 | 'address' => 'nullable|max:255', 34 | 'website' => 'nullable|url|max:255', 35 | 'notes' => 'nullable|max:255', 36 | 'is_active' => 'required|boolean', 37 | ]; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/views/auth/passwords/change.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.app') 2 | 3 | @section('title', __('auth.change_password')) 4 | 5 | @section('content') 6 | 9 | 10 |
    11 |
    12 | {!! Form::open(['route' => 'auth.change-password', 'method' => 'patch']) !!} 13 |
    14 | {!! FormField::password('old_password', ['label' => false, 'placeholder' => __('auth.old_password')]) !!} 15 | {!! FormField::password('password', ['label' => false, 'placeholder' => __('auth.new_password')]) !!} 16 | {!! FormField::password('password_confirmation', ['label' => false, 'placeholder' => __('auth.new_password_confirmation')]) !!} 17 |
    18 | 22 | {!! Form::close() !!} 23 |
    24 |
    25 | @endsection 26 | -------------------------------------------------------------------------------- /resources/views/customers/partials/nav-tabs.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 19 |
    20 | -------------------------------------------------------------------------------- /database/migrations/2017_10_26_134455_create_customers_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 18 | $table->string('name', 60); 19 | $table->string('email')->nullable()->unique(); 20 | $table->string('phone')->nullable(); 21 | $table->string('pic')->nullable(); 22 | $table->string('address')->nullable(); 23 | $table->string('website')->nullable(); 24 | $table->string('notes')->nullable(); 25 | $table->boolean('is_active')->default(1); 26 | $table->timestamps(); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * 33 | * @return void 34 | */ 35 | public function down() 36 | { 37 | Schema::dropIfExists('customers'); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /resources/views/pages/partials/dashboard-nav-tabs.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 24 |
    25 | -------------------------------------------------------------------------------- /tests/TestCase.php: -------------------------------------------------------------------------------- 1 | createUser('admin', $userDataOverrides); 15 | $this->actingAs($user); 16 | 17 | return $user; 18 | } 19 | 20 | protected function userSigningIn($userDataOverrides = []) 21 | { 22 | $user = $this->createUser('worker', $userDataOverrides); 23 | $this->actingAs($user); 24 | 25 | return $user; 26 | } 27 | 28 | protected function createUser($role = 'admin', $userDataOverrides = []) 29 | { 30 | $user = factory(User::class)->create($userDataOverrides); 31 | $user->assignRole($role); 32 | 33 | return $user; 34 | } 35 | 36 | protected function assertFileExistsThenDelete($filePath, $message = '') 37 | { 38 | $this->assertTrue(file_exists($filePath), $message); 39 | 40 | unlink($filePath); 41 | $this->assertFalse(file_exists($filePath)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Entities/BaseRepository.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | abstract class BaseRepository extends EloquentRepository 15 | { 16 | /** 17 | * Get collection of customers. 18 | * 19 | * @return \Illuminate\Database\Eloquent\Collection 20 | */ 21 | public function getCustomersList() 22 | { 23 | return Customer::where('is_active', 1) 24 | ->orderBy('name') 25 | ->pluck('name', 'id'); 26 | } 27 | 28 | /** 29 | * Get collection of workers. 30 | * 31 | * @return \Illuminate\Database\Eloquent\Collection 32 | */ 33 | public function getWorkersList() 34 | { 35 | return User::orderBy('name')->pluck('name', 'id'); 36 | } 37 | 38 | /** 39 | * Get Job by it's id. 40 | * 41 | * @param int $jobId 42 | * @return \App\Entities\Projects\Job 43 | */ 44 | public function requireJobById($jobId) 45 | { 46 | return Job::findOrFail($jobId); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /database/migrations/2016_11_15_151228_create_payments_table.php: -------------------------------------------------------------------------------- 1 | increments('id'); 17 | $table->integer('project_id')->unsigned(); 18 | $table->integer('amount')->unsigned(); 19 | $table->boolean('type_id')->default(1)->comment('1:project, 2: add_job, 3:maintenance'); 20 | $table->boolean('in_out')->default(1)->comment('0: out, 1: in'); 21 | $table->date('date'); 22 | $table->string('description'); 23 | $table->string('partner_type'); 24 | $table->integer('partner_id')->unsigned(); 25 | $table->timestamps(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::drop('payments'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/Http/Controllers/Projects/ActivityController.php: -------------------------------------------------------------------------------- 1 | where(function ($query) use ($project) { 16 | $query->where('object_id', $project->id); 17 | $query->where('object_type', 'projects'); 18 | }); 19 | 20 | $activityQuery->orWhere(function ($query) use ($project) { 21 | $query->whereIn('object_id', $project->jobs->pluck('id')); 22 | $query->where('object_type', 'jobs'); 23 | }); 24 | 25 | $activityQuery->orWhere(function ($query) use ($project) { 26 | $query->whereIn('object_id', $project->tasks->pluck('id')); 27 | $query->where('object_type', 'tasks'); 28 | }); 29 | 30 | $activities = $activityQuery->latest()->paginate(50); 31 | 32 | return view('projects.activities.index', compact('project', 'activities')); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /bootstrap/autoload.php: -------------------------------------------------------------------------------- 1 | getClientOriginalExtension(), $parameters); 22 | }); 23 | 24 | Relation::morphMap([ 25 | 'projects' => 'App\Entities\Projects\Project', 26 | 'issues' => 'App\Entities\Projects\Issue', 27 | 'jobs' => 'App\Entities\Projects\Job', 28 | 'tasks' => 'App\Entities\Projects\Task', 29 | ]); 30 | Paginator::useBootstrap(); 31 | } 32 | 33 | /** 34 | * Register any application services. 35 | * 36 | * @return void 37 | */ 38 | public function register() 39 | { 40 | // 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/lang/en/vendor.php: -------------------------------------------------------------------------------- 1 | 'Vendor', 6 | 'list' => 'Vendor List', 7 | 'detail' => 'Vendor Detail', 8 | 'search' => 'Search Vendor', 9 | 'select' => 'Select Vendor', 10 | 'not_found' => 'Vendor not found.', 11 | 'empty' => 'Vendor list is empty.', 12 | 'back_to_show' => 'Back to Vendor Detail', 13 | 'back_to_index' => 'Back to Vendor List', 14 | 15 | // Actions 16 | 'create' => 'Create new Vendor', 17 | 'created' => 'Vendor has been created.', 18 | 'show' => 'Vendor Detail', 19 | 'edit' => 'Edit Vendor', 20 | 'update' => 'Update Vendor', 21 | 'updated' => 'Vendor has been updated.', 22 | 'delete' => 'Delete Vendor', 23 | 'delete_confirm' => 'Are you sure to delete this Vendor?', 24 | 'deleted' => 'Vendor has been deleted.', 25 | 'undeleted' => 'Vendor not deleted.', 26 | 'undeleteable' => 'Vendor can not be deleted.', 27 | 28 | // Attributes 29 | 'name' => 'Vendor Name', 30 | 'website' => 'Vendor Website', 31 | 'description' => 'Vendor Description', 32 | ]; 33 | -------------------------------------------------------------------------------- /resources/lang/id/file.php: -------------------------------------------------------------------------------- 1 | 'File', 6 | 'list' => 'Daftar File', 7 | 'search' => 'Cari File', 8 | 'not_found' => 'File tidak ditemukan', 9 | 'empty' => 'Belum ada File', 10 | 'back_to_index' => 'Kembali ke daftar File', 11 | 12 | // Actions 13 | 'create' => 'Upload File Baru', 14 | 'created' => 'Upload File baru telah berhasil.', 15 | 'edit' => 'Edit File', 16 | 'update' => 'Update File', 17 | 'updated' => 'Update data File telah berhasil.', 18 | 'delete' => 'Hapus File', 19 | 'delete_confirm' => 'Anda yakin akan menghapus File ini?', 20 | 'deleted' => 'Hapus data File telah berhasil.', 21 | 'undeleted' => 'Data File gagal dihapus.', 22 | 'undeleteable' => 'Data File tidak dapat dihapus.', 23 | 'select' => 'Pilih File', 24 | 'upload' => 'Upload File', 25 | 'download' => 'Download', 26 | 27 | // Attributes 28 | 'title' => 'Nama File', 29 | 'description' => 'Deskripsi File', 30 | 'size' => 'Ukuran File', 31 | 'updated_at' => 'Tanggal', 32 | ]; 33 | -------------------------------------------------------------------------------- /resources/views/subscriptions/partials/subscription-show.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 |
    {{ __('subscription.name') }}{{ $subscription->name }}
    {{ __('subscription.price') }}{{ format_money($subscription->price) }}
    {{ __('subscription.type') }}{{ $subscription->type }}
    {{ __('subscription.start_date') }}{{ date_id($subscription->start_date) }}
    {{ __('subscription.due_date') }}{{ date_id($subscription->due_date) }}
    {{ __('subscription.customer') }}{{ $subscription->customer->nameLink() }}
    {{ __('subscription.project') }} 12 | {{ link_to_route('projects.subscriptions', $subscription->project->name, [$subscription->project_id]) }} 13 |
    {{ __('subscription.vendor') }}{{ $subscription->vendor->name }}
    {{ __('subscription.notes') }}{!! nl2br($subscription->notes) !!}
    19 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | app/ 6 | 7 | 8 | 9 | 10 | ./tests/ 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/Http/Controllers/Invoices/DuplicationController.php: -------------------------------------------------------------------------------- 1 | draftCollection = new InvoiceDraftCollection(); 18 | } 19 | 20 | public function store(Invoice $invoice) 21 | { 22 | $draft = new InvoiceDraft(); 23 | $this->draftCollection->add($draft); 24 | 25 | foreach ($invoice->items as $existingItem) { 26 | $item = new Item(['description' => $existingItem['description'], 'amount' => $existingItem['amount']]); 27 | $this->draftCollection->addItemToDraft($draft->draftKey, $item); 28 | } 29 | $draft->date = today()->format('Y-m-d'); 30 | $draft->projectId = $invoice->project_id; 31 | $draft->notes = $invoice->notes; 32 | 33 | return redirect()->route('invoice-drafts.show', $draft->draftKey); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/lang/de/file.php: -------------------------------------------------------------------------------- 1 | 'Datei', 6 | 'list' => 'Dateiliste', 7 | 'search' => 'Dateisuche', 8 | 'not_found' => 'Datei nicht gefunden.', 9 | 'empty' => 'Dateiliste ist leer.', 10 | 'back_to_index' => 'Zurück zur Dateiliste', 11 | 12 | // Actions 13 | 'create' => 'neue Datei hochladen', 14 | 'created' => 'Neue Datei wurde erstellt.', 15 | 'edit' => 'Datei bearbeiten', 16 | 'update' => 'Datei hochladen', 17 | 'updated' => 'Neue Datei wurde aktualisiert.', 18 | 'delete' => 'Datei löschen', 19 | 'delete_confirm' => 'Wollen Sie wirklich diese Datei löschen?', 20 | 'deleted' => 'Datei wurde gelöscht.', 21 | 'undeleted' => 'Datei nicht gelöscht.', 22 | 'undeleteable' => 'Datei kann nicht gelöscht werden.', 23 | 'select' => 'Datei auswählen', 24 | 'upload' => 'Datei hochladen', 25 | 'download' => 'Download', 26 | 27 | // Attributes 28 | 'title' => 'Dateiname', 29 | 'description' => 'Dateibeschreibung', 30 | 'size' => 'Dateigröße', 31 | 'updated_at' => 'aktualisiert am', 32 | ]; 33 | -------------------------------------------------------------------------------- /resources/views/errors/503.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | Be right back. 4 | 5 | 6 | 7 | 35 | 36 | 37 |
    38 |
    39 |
    Be right back.
    40 |
    41 |
    42 | 43 | 44 | -------------------------------------------------------------------------------- /tests/Feature/Api/FetchPartnerListTest.php: -------------------------------------------------------------------------------- 1 | createUser('admin'); 18 | $customer = factory(Customer::class)->create(); 19 | 20 | $this->postJson(route('api.customers.index'), [], [ 21 | 'Authorization' => 'Bearer '.$user->api_token, 22 | ]); 23 | 24 | $this->seeJson([ 25 | $customer->id => $customer->name, 26 | ]); 27 | } 28 | 29 | /** @test */ 30 | public function user_can_fetch_vendor_listing() 31 | { 32 | $user = $this->createUser('admin'); 33 | $vendor = factory(Vendor::class)->create(); 34 | 35 | $this->postJson(route('api.vendors.index'), [], [ 36 | 'Authorization' => 'Bearer '.$user->api_token, 37 | ]); 38 | 39 | $this->seeJson([ 40 | $vendor->id => $vendor->name, 41 | ]); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /app/Http/Middleware/Role.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class Role 13 | { 14 | /** 15 | * Handle an incoming request. 16 | * 17 | * @param \Illuminate\Http\Request $request 18 | * @param \Closure $next 19 | * @return mixed 20 | */ 21 | public function handle($request, Closure $next, $names) 22 | { 23 | $nameArray = explode('|', $names); 24 | 25 | if (auth()->check() == false) { 26 | return $request->expectsJson() 27 | ? response()->json(['message' => 'Forbidden.'], 403) 28 | : redirect()->guest('login'); 29 | } 30 | 31 | // Cek apakah grup user ada di dalam array $nameArray? 32 | if (auth()->user()->hasRoles($nameArray) == false) { 33 | if ($request->expectsJson()) { 34 | return response()->json(['message' => 'Forbidden.'], 403); 35 | } 36 | 37 | flash(__('auth.unauthorized_access', ['url' => $request->path()]), 'danger'); 38 | 39 | return redirect()->route('home'); 40 | } 41 | 42 | return $next($request); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /resources/views/jobs/partials/job-dates.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
     {{ __('job.starts') }}{{ __('job.ends') }}{{ __('job.duration') }}
    {{ __('job.target') }}{{ $job->target_start_date }}{{ $job->target_end_date }}{{ Carbon::parse($job->target_start_date)->diffInDays(Carbon::parse($job->target_end_date), false) }} {{ __('time.days') }}
    {{ __('job.actual') }}{{ $job->actual_start_date }}{{ $job->actual_end_date }}{{ Carbon::parse($job->actual_start_date)->diffInDays(Carbon::parse($job->actual_end_date), false) }} {{ __('time.days') }}
    23 | -------------------------------------------------------------------------------- /resources/lang/id/vendor.php: -------------------------------------------------------------------------------- 1 | 'Vendor', 6 | 'list' => 'Daftar Vendor', 7 | 'detail' => 'Detail Vendor', 8 | 'search' => 'Cari Vendor', 9 | 'select' => 'Pilih Vendor', 10 | 'not_found' => 'Vendor tidak ditemukan', 11 | 'empty' => 'Belum ada Vendor', 12 | 'back_to_show' => 'Kembali ke detail Vendor', 13 | 'back_to_index' => 'Kembali ke daftar Vendor', 14 | 15 | // Actions 16 | 'create' => 'Input Vendor Baru', 17 | 'created' => 'Input Vendor baru telah berhasil.', 18 | 'show' => 'Detail Vendor', 19 | 'edit' => 'Edit Vendor', 20 | 'update' => 'Update Vendor', 21 | 'updated' => 'Update data Vendor telah berhasil.', 22 | 'delete' => 'Hapus Vendor', 23 | 'delete_confirm' => 'Anda yakin akan menghapus Vendor ini?', 24 | 'deleted' => 'Hapus data Vendor telah berhasil.', 25 | 'undeleted' => 'Data Vendor gagal dihapus.', 26 | 'undeleteable' => 'Data Vendor tidak dapat dihapus.', 27 | 28 | // Attributes 29 | 'name' => 'Nama Vendor', 30 | 'website' => 'Website Vendor', 31 | 'description' => 'Deskripsi Vendor', 32 | ]; 33 | -------------------------------------------------------------------------------- /app/Http/Controllers/Reports/LogFileController.php: -------------------------------------------------------------------------------- 1 | getMTime(), $b->getMTime()); 20 | }); 21 | 22 | return view('reports.log-files', compact('logFiles')); 23 | } 24 | 25 | public function show($fileName) 26 | { 27 | if (file_exists(storage_path('logs/'.$fileName))) { 28 | return response()->file(storage_path('logs/'.$fileName), ['content-type' => 'text/plain']); 29 | } 30 | 31 | return 'Invalid file name.'; 32 | } 33 | 34 | public function download($fileName) 35 | { 36 | if (file_exists(storage_path('logs/'.$fileName))) { 37 | return response()->download(storage_path('logs/'.$fileName), env('APP_ENV').'.'.$fileName); 38 | } 39 | 40 | return 'Invalid file name.'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /resources/lang/en/bank_account.php: -------------------------------------------------------------------------------- 1 | 'Bank Account', 6 | 'list' => 'Bank Account List', 7 | 'empty' => 'Bank Account list is empty', 8 | 'back_to_index' => 'Back to Bank Account list', 9 | 10 | // Actions 11 | 'import' => 'Import Bank Account', 12 | 'imported' => ':count bank account(s) has imported.', 13 | 'create' => 'Create new Bank Account', 14 | 'created' => 'New Bank Account has been created.', 15 | 'show' => 'Show Bank Account detail', 16 | 'edit' => 'Edit Bank Account', 17 | 'update' => 'Update Bank Account', 18 | 'updated' => 'Bank Account data has been updated.', 19 | 'delete' => 'Delete Bank Account', 20 | 'delete_confirm' => 'Are you sure to delete this Bank Account data?', 21 | 'deleted' => 'Bank Account data has been deleted.', 22 | 'undeleted' => 'Bank Account Data not deleted.', 23 | 'undeleteable' => 'Bank Account Data can not be deleted.', 24 | 25 | // Attributes 26 | 'name' => 'Bank Name', 27 | 'number' => 'Account Number', 28 | 'account_name' => 'Account Name', 29 | 'description' => 'Description', 30 | ]; 31 | -------------------------------------------------------------------------------- /resources/lang/id/task.php: -------------------------------------------------------------------------------- 1 | 'Task', 6 | 'list' => 'Daftar Task', 7 | 'empty' => 'Belum ada Task', 8 | 'search' => 'Cari Task', 9 | 'found' => 'Task ditemukan', 10 | 'not_found' => 'Task tidak ditemukan', 11 | 'back_to_index' => 'Kembali ke daftar Task', 12 | 'move_to_other_job' => 'Pindahkan ke Job lain', 13 | 14 | // Actions 15 | 'create' => 'Input Task Baru', 16 | 'created' => 'Input Task baru telah berhasil.', 17 | 'show' => 'Detail Task', 18 | 'edit' => 'Edit Task', 19 | 'update' => 'Update Task', 20 | 'updated' => 'Update data Task telah berhasil.', 21 | 'delete' => 'Hapus Task', 22 | 'deleted' => 'Hapus data Task telah berhasil.', 23 | 'undeleted' => 'Data Task gagal dihapus.', 24 | 'set_done' => 'Set Selesai', 25 | 26 | 'set_as_job' => 'Set Menjadi Job', 27 | 'set_as_job_confirm' => 'Anda yakin mengubah task ini menjadi sebuah Job?', 28 | 'upgraded_as_job' => 'Task telah menjadi Job.', 29 | 30 | // Attributes 31 | 'name' => 'Nama Task', 32 | 'progress' => 'Progress', 33 | 'description' => 'Deskripsi Task', 34 | ]; 35 | --------------------------------------------------------------------------------