From 84ca2e15ba5fd1a82e5caa1c0eacb16541d97835 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 26 Oct 2024 22:43:00 +0700 Subject: [PATCH 001/184] hapus migration yang tidak digunakan --- .../0001_01_01_000002_create_jobs_table.php | 57 ------------------- .../2024_10_03_031706_create_posts_table.php | 30 ---------- 2 files changed, 87 deletions(-) delete mode 100644 database/migrations/0001_01_01_000002_create_jobs_table.php delete mode 100644 database/migrations/2024_10_03_031706_create_posts_table.php diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php deleted file mode 100644 index 425e705..0000000 --- a/database/migrations/0001_01_01_000002_create_jobs_table.php +++ /dev/null @@ -1,57 +0,0 @@ -id(); - $table->string('queue')->index(); - $table->longText('payload'); - $table->unsignedTinyInteger('attempts'); - $table->unsignedInteger('reserved_at')->nullable(); - $table->unsignedInteger('available_at'); - $table->unsignedInteger('created_at'); - }); - - Schema::create('job_batches', function (Blueprint $table) { - $table->string('id')->primary(); - $table->string('name'); - $table->integer('total_jobs'); - $table->integer('pending_jobs'); - $table->integer('failed_jobs'); - $table->longText('failed_job_ids'); - $table->mediumText('options')->nullable(); - $table->integer('cancelled_at')->nullable(); - $table->integer('created_at'); - $table->integer('finished_at')->nullable(); - }); - - Schema::create('failed_jobs', function (Blueprint $table) { - $table->id(); - $table->string('uuid')->unique(); - $table->text('connection'); - $table->text('queue'); - $table->longText('payload'); - $table->longText('exception'); - $table->timestamp('failed_at')->useCurrent(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('jobs'); - Schema::dropIfExists('job_batches'); - Schema::dropIfExists('failed_jobs'); - } -}; diff --git a/database/migrations/2024_10_03_031706_create_posts_table.php b/database/migrations/2024_10_03_031706_create_posts_table.php deleted file mode 100644 index e6af613..0000000 --- a/database/migrations/2024_10_03_031706_create_posts_table.php +++ /dev/null @@ -1,30 +0,0 @@ -id(); - $table->foreignId('user_id')->constrained()->cascadeOnDelete(); - $table->string('title'); - $table->text('body'); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('posts'); - } -}; From b658075bba45d5a82385eb73db1b108fcceb3d4d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 29 Oct 2024 08:12:02 +0700 Subject: [PATCH 002/184] tambah table customers --- app/Http/Controllers/CustomerController.php | 84 +++++++++++++++++++ app/Models/Customer.php | 27 ++++++ ...24_10_29_003420_create_customers_table.php | 39 +++++++++ database/seeders/CustomerSeeder.php | 37 ++++++++ database/seeders/DatabaseSeeder.php | 5 +- database/seeders/PostSeeder.php | 17 ---- routes/api.php | 4 +- vite.config.js | 6 +- 8 files changed, 195 insertions(+), 24 deletions(-) create mode 100644 app/Http/Controllers/CustomerController.php create mode 100644 app/Models/Customer.php create mode 100644 database/migrations/2024_10_29_003420_create_customers_table.php create mode 100644 database/seeders/CustomerSeeder.php delete mode 100644 database/seeders/PostSeeder.php diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php new file mode 100644 index 0000000..7d72d3f --- /dev/null +++ b/app/Http/Controllers/CustomerController.php @@ -0,0 +1,84 @@ +json($customers); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request): JsonResponse + { + $validatedData = $request->validate([ + 'name' => 'required|string|max:100', + 'alamat' => 'required|string|max:255', + 'whatsapp' => 'required|string|max:15', + 'kategori' => 'required|string|max:50', + 'pekerjaan' => 'required|string|max:50', + 'bank' => 'required|string|max:50', + 'sertifikat' => 'required|string|max:50', + 'nilai_transaksi' => 'required|numeric', + 'harga_real' => 'required|numeric', + 'harga_kesepakatan' => 'required|numeric', + 'data_pajak_pembeli' => 'required|string|max:100', + 'data_pajak_penjual' => 'required|string|max:100', + ]); + + $customer = Customer::create($validatedData); + return response()->json($customer, 201); + } + + /** + * Display the specified resource. + */ + public function show(Customer $customer): JsonResponse + { + return response()->json($customer); + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Customer $customer): JsonResponse + { + $validatedData = $request->validate([ + 'name' => 'string|max:100', + 'alamat' => 'string|max:255', + 'whatsapp' => 'string|max:15', + 'kategori' => 'string|max:50', + 'pekerjaan' => 'string|max:50', + 'bank' => 'string|max:50', + 'sertifikat' => 'string|max:50', + 'nilai_transaksi' => 'numeric', + 'harga_real' => 'numeric', + 'harga_kesepakatan' => 'numeric', + 'data_pajak_pembeli' => 'string|max:100', + 'data_pajak_penjual' => 'string|max:100', + ]); + + $customer->update($validatedData); + return response()->json($customer); + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Customer $customer): JsonResponse + { + $customer->delete(); + return response()->json(null, 204); + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php new file mode 100644 index 0000000..2af26c4 --- /dev/null +++ b/app/Models/Customer.php @@ -0,0 +1,27 @@ +id(); + $table->string('name', 100); + $table->string('alamat', 255); + $table->string('whatsapp', 15); + $table->string('kategori', 50); + $table->string('pekerjaan', 50); + $table->string('bank', 50); + $table->string('sertifikat', 50); + $table->decimal('nilai_transaksi', 15, 2); + $table->decimal('harga_real', 15, 2); + $table->decimal('harga_kesepakatan', 15, 2); + $table->string('data_pajak_pembeli', 100); + $table->string('data_pajak_penjual', 100); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('customers'); + } +}; diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php new file mode 100644 index 0000000..7f8bfe7 --- /dev/null +++ b/database/seeders/CustomerSeeder.php @@ -0,0 +1,37 @@ +insert([ + 'name' => $faker->name, + 'alamat' => $faker->address, + 'whatsapp' => $faker->phoneNumber, + 'kategori' => $faker->word, + 'pekerjaan' => $faker->jobTitle, + 'bank' => $faker->company, + 'sertifikat' => $faker->word, + 'nilai_transaksi' => $faker->randomFloat(2, 1000, 100000), // random float between 1000 and 100000 + 'harga_real' => $faker->randomFloat(2, 1000, 100000), + 'harga_kesepakatan' => $faker->randomFloat(2, 1000, 100000), + 'data_pajak_pembeli' => $faker->word, + 'data_pajak_penjual' => $faker->word, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d01a0ef..91ed73b 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -13,11 +13,12 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); - + User::factory()->count(10)->create(); User::factory()->create([ 'name' => 'Test User', 'email' => 'test@example.com', + 'password' => bcrypt('password'), ]); + $this->call(CustomerSeeder::class); } } diff --git a/database/seeders/PostSeeder.php b/database/seeders/PostSeeder.php deleted file mode 100644 index 9132da7..0000000 --- a/database/seeders/PostSeeder.php +++ /dev/null @@ -1,17 +0,0 @@ -user(); })->middleware('auth:sanctum'); -Route::apiResource('posts', PostController::class); +Route::apiResource('customers', CustomerController::class)->middleware('auth:sanctum'); Route::post('/register', [AuthController::class, 'register']); Route::post('/login', [AuthController::class, 'login']); diff --git a/vite.config.js b/vite.config.js index 421b569..498ee23 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,10 +1,10 @@ -import { defineConfig } from 'vite'; -import laravel from 'laravel-vite-plugin'; +import { defineConfig } from "vite"; +import laravel from "laravel-vite-plugin"; export default defineConfig({ plugins: [ laravel({ - input: ['resources/css/app.css', 'resources/js/app.js'], + input: ["resources/css/app.css", "resources/js/app.js"], refresh: true, }), ], From f4fd28239ae4f8ccf02e73f5ced9f33386b9521b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 31 Oct 2024 12:53:10 +0700 Subject: [PATCH 003/184] ganti breeze --- .env.example | 2 + .github/workflows/issues.yml | 12 + .github/workflows/pull-requests.yml | 12 + .github/workflows/tests.yml | 47 ++ .github/workflows/update-changelog.yml | 13 + .gitignore | 1 + .styleci.yml | 9 + CHANGELOG.md | 92 +++ .../Auth/AuthenticatedSessionController.php | 38 ++ ...mailVerificationNotificationController.php | 25 + .../Auth/NewPasswordController.php | 53 ++ .../Auth/PasswordResetLinkController.php | 39 ++ .../Auth/RegisteredUserController.php | 41 ++ .../Auth/VerifyEmailController.php | 31 + app/Http/Controllers/AuthController.php | 60 -- app/Http/Controllers/CustomerController.php | 84 --- app/Http/Controllers/PostController.php | 79 --- app/Http/Middleware/EnsureEmailIsVerified.php | 27 + app/Http/Requests/Auth/LoginRequest.php | 85 +++ app/Models/Customer.php | 27 - app/Models/Post.php | 21 - app/Models/User.php | 9 +- app/Policies/PostPolicy.php | 20 - app/Providers/AppServiceProvider.php | 5 +- bootstrap/app.php | 8 + composer.json | 8 +- composer.lock | 578 +++++++++++------- config/cors.php | 34 ++ config/sanctum.php | 7 +- database/factories/PostFactory.php | 23 - .../0001_01_01_000002_create_jobs_table.php | 57 ++ ...24_10_29_003420_create_customers_table.php | 39 -- ...3_create_personal_access_tokens_table.php} | 0 database/seeders/CustomerSeeder.php | 37 -- database/seeders/DatabaseSeeder.php | 5 +- package.json | 13 - postcss.config.js | 6 + resources/css/app.css | 0 resources/js/app.js | 1 - resources/js/bootstrap.js | 4 - resources/views/.gitkeep | 1 + resources/views/welcome.blade.php | 172 ------ routes/api.php | 13 +- routes/auth.php | 37 ++ routes/web.php | 6 + tailwind.config.js | 20 + tests/Feature/Auth/AuthenticationTest.php | 47 ++ tests/Feature/Auth/EmailVerificationTest.php | 49 ++ tests/Feature/Auth/PasswordResetTest.php | 49 ++ tests/Feature/Auth/RegistrationTest.php | 24 + vite.config.js | 11 - 51 files changed, 1245 insertions(+), 836 deletions(-) create mode 100644 .github/workflows/issues.yml create mode 100644 .github/workflows/pull-requests.yml create mode 100644 .github/workflows/tests.yml create mode 100644 .github/workflows/update-changelog.yml create mode 100644 .styleci.yml create mode 100644 CHANGELOG.md create mode 100644 app/Http/Controllers/Auth/AuthenticatedSessionController.php create mode 100644 app/Http/Controllers/Auth/EmailVerificationNotificationController.php create mode 100644 app/Http/Controllers/Auth/NewPasswordController.php create mode 100644 app/Http/Controllers/Auth/PasswordResetLinkController.php create mode 100644 app/Http/Controllers/Auth/RegisteredUserController.php create mode 100644 app/Http/Controllers/Auth/VerifyEmailController.php delete mode 100644 app/Http/Controllers/AuthController.php delete mode 100644 app/Http/Controllers/CustomerController.php delete mode 100644 app/Http/Controllers/PostController.php create mode 100644 app/Http/Middleware/EnsureEmailIsVerified.php create mode 100644 app/Http/Requests/Auth/LoginRequest.php delete mode 100644 app/Models/Customer.php delete mode 100644 app/Models/Post.php delete mode 100644 app/Policies/PostPolicy.php create mode 100644 config/cors.php delete mode 100644 database/factories/PostFactory.php create mode 100644 database/migrations/0001_01_01_000002_create_jobs_table.php delete mode 100644 database/migrations/2024_10_29_003420_create_customers_table.php rename database/migrations/{2024_10_03_022302_create_personal_access_tokens_table.php => 2024_10_31_042843_create_personal_access_tokens_table.php} (100%) delete mode 100644 database/seeders/CustomerSeeder.php delete mode 100644 package.json create mode 100644 postcss.config.js delete mode 100644 resources/css/app.css delete mode 100644 resources/js/app.js delete mode 100644 resources/js/bootstrap.js create mode 100644 resources/views/.gitkeep delete mode 100644 resources/views/welcome.blade.php create mode 100644 routes/auth.php create mode 100644 tailwind.config.js create mode 100644 tests/Feature/Auth/AuthenticationTest.php create mode 100644 tests/Feature/Auth/EmailVerificationTest.php create mode 100644 tests/Feature/Auth/PasswordResetTest.php create mode 100644 tests/Feature/Auth/RegistrationTest.php delete mode 100644 vite.config.js diff --git a/.env.example b/.env.example index 2a4a8b7..a1b3de4 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,8 @@ APP_FAKER_LOCALE=en_US APP_MAINTENANCE_DRIVER=file # APP_MAINTENANCE_STORE=database +PHP_CLI_SERVER_WORKERS=4 + BCRYPT_ROUNDS=12 LOG_CHANNEL=stack diff --git a/.github/workflows/issues.yml b/.github/workflows/issues.yml new file mode 100644 index 0000000..9634a0e --- /dev/null +++ b/.github/workflows/issues.yml @@ -0,0 +1,12 @@ +name: issues + +on: + issues: + types: [labeled] + +permissions: + issues: write + +jobs: + help-wanted: + uses: laravel/.github/.github/workflows/issues.yml@main diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml new file mode 100644 index 0000000..18b32b3 --- /dev/null +++ b/.github/workflows/pull-requests.yml @@ -0,0 +1,12 @@ +name: pull requests + +on: + pull_request_target: + types: [opened] + +permissions: + pull-requests: write + +jobs: + uneditable: + uses: laravel/.github/.github/workflows/pull-requests.yml@main diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..03601bd --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,47 @@ +name: Tests + +on: + push: + branches: + - master + - '*.x' + pull_request: + schedule: + - cron: '0 0 * * *' + +permissions: + contents: read + +jobs: + tests: + runs-on: ubuntu-latest + + strategy: + fail-fast: true + matrix: + php: [8.2, 8.3] + + name: PHP ${{ matrix.php }} + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite + coverage: none + + - name: Install Composer dependencies + run: composer install --prefer-dist --no-interaction --no-progress + + - name: Copy environment file + run: cp .env.example .env + + - name: Generate app key + run: php artisan key:generate + + - name: Execute tests + run: vendor/bin/phpunit diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml new file mode 100644 index 0000000..ebda620 --- /dev/null +++ b/.github/workflows/update-changelog.yml @@ -0,0 +1,13 @@ +name: update changelog + +on: + release: + types: [released] + +permissions: {} + +jobs: + update: + permissions: + contents: write + uses: laravel/.github/.github/workflows/update-changelog.yml@main diff --git a/.gitignore b/.gitignore index afa306b..c3ea31b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /public/hot /public/storage /storage/*.key +/storage/pail /vendor .env .env.backup diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..9daadf1 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,9 @@ +php: + preset: laravel + disabled: + - no_unused_imports + finder: + not-name: + - index.php +js: true +css: true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..201a0d3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,92 @@ +# Release Notes + +## [Unreleased](https://github.com/laravel/laravel/compare/v11.3.1...11.x) + +## [v11.3.1](https://github.com/laravel/laravel/compare/v11.3.0...v11.3.1) - 2024-10-15 + +**Full Changelog**: https://github.com/laravel/laravel/compare/v11.3.0...v11.3.1 + +## [v11.3.0](https://github.com/laravel/laravel/compare/v11.2.1...v11.3.0) - 2024-10-14 + +* Add Tailwind, "composer run dev" by [@taylorotwell](https://github.com/taylorotwell) in https://github.com/laravel/laravel/pull/6463 + +## [v11.2.1](https://github.com/laravel/laravel/compare/v11.2.0...v11.2.1) - 2024-10-08 + +* [11.x] Collision Version Upgrade by [@amdad121](https://github.com/amdad121) in https://github.com/laravel/laravel/pull/6454 +* [11.x] factory-generics-in-user-model by [@MrPunyapal](https://github.com/MrPunyapal) in https://github.com/laravel/laravel/pull/6453 +* Update welcome.blade.php to add missing alt tag by [@mezotv](https://github.com/mezotv) in https://github.com/laravel/laravel/pull/6462 + +## [v11.2.0](https://github.com/laravel/laravel/compare/v11.1.5...v11.2.0) - 2024-09-11 + +* Update .gitignore with Zed Editor by [@fahadkhan1740](https://github.com/fahadkhan1740) in https://github.com/laravel/laravel/pull/6449 +* Laracon 2024 feature update by [@taylorotwell](https://github.com/taylorotwell) in https://github.com/laravel/laravel/pull/6450 + +## [v11.1.5](https://github.com/laravel/laravel/compare/v11.1.4...v11.1.5) - 2024-08-14 + +* Update axios by [@laserhybiz](https://github.com/laserhybiz) in https://github.com/laravel/laravel/pull/6440 + +## [v11.1.4](https://github.com/laravel/laravel/compare/v11.1.3...v11.1.4) - 2024-07-16 + +**Full Changelog**: https://github.com/laravel/laravel/compare/v11.1.3...v11.1.4 + +## [v11.1.3](https://github.com/laravel/laravel/compare/v11.1.2...v11.1.3) - 2024-07-03 + +* [11.x] Comment maintenance store by [@timacdonald](https://github.com/timacdonald) in https://github.com/laravel/laravel/pull/6429 + +## [v11.1.2](https://github.com/laravel/laravel/compare/v11.1.1...v11.1.2) - 2024-06-20 + +* Expose lock table name by [@nhedger](https://github.com/nhedger) in https://github.com/laravel/laravel/pull/6423 + +## [v11.1.1](https://github.com/laravel/laravel/compare/v11.1.0...v11.1.1) - 2024-06-04 + +* Format the first letter of `drivers` to lowercase by [@maru0914](https://github.com/maru0914) in https://github.com/laravel/laravel/pull/6413 + +## [v11.1.0](https://github.com/laravel/laravel/compare/v11.0.9...v11.1.0) - 2024-05-28 + +* [11.x] Removes `--dev` dependencies by [@nunomaduro](https://github.com/nunomaduro) in https://github.com/laravel/laravel/pull/6406 + +## [v11.0.9](https://github.com/laravel/laravel/compare/v11.0.8...v11.0.9) - 2024-05-16 + +* Updated SMTP mail config to use a valid EHLO domain by [@rcerljenko](https://github.com/rcerljenko) in https://github.com/laravel/laravel/pull/6402 + +## [v11.0.8](https://github.com/laravel/laravel/compare/v11.0.7...v11.0.8) - 2024-05-13 + +* Add .phpactor.json to .gitignore by [@princejohnsantillan](https://github.com/princejohnsantillan) in https://github.com/laravel/laravel/pull/6400 + +## [v11.0.7](https://github.com/laravel/laravel/compare/v11.0.6...v11.0.7) - 2024-05-03 + +* Remove obsolete driver option by [@u01jmg3](https://github.com/u01jmg3) in https://github.com/laravel/laravel/pull/6395 + +## [v11.0.6](https://github.com/laravel/laravel/compare/v11.0.5...v11.0.6) - 2024-04-09 + +* Fix PHPUnit constraint by [@szepeviktor](https://github.com/szepeviktor) in https://github.com/laravel/laravel/pull/6389 +* [11.x] Add missing roundrobin transport driver config by [@u01jmg3](https://github.com/u01jmg3) in https://github.com/laravel/laravel/pull/6392 + +## [v11.0.5](https://github.com/laravel/laravel/compare/v11.0.4...v11.0.5) - 2024-03-26 + +* [11.x] Use PHPUnit v11 by [@philbates35](https://github.com/philbates35) in https://github.com/laravel/laravel/pull/6385 + +## [v11.0.4](https://github.com/laravel/laravel/compare/v11.0.3...v11.0.4) - 2024-03-15 + +* [11.x] Removed useless null parameter for env helper (cache.php) by [@siarheipashkevich](https://github.com/siarheipashkevich) in https://github.com/laravel/laravel/pull/6374 +* [11.x] Removed useless null parameter for env helper (queue.php) by [@siarheipashkevich](https://github.com/siarheipashkevich) in https://github.com/laravel/laravel/pull/6373 +* [11.x] Fix retry_after to be an integer by [@driesvints](https://github.com/driesvints) in https://github.com/laravel/laravel/pull/6377 +* [11.x] Fix on hover animation and ring by [@michaelnabil230](https://github.com/michaelnabil230) in https://github.com/laravel/laravel/pull/6376 + +## [v11.0.3](https://github.com/laravel/laravel/compare/v11.0.2...v11.0.3) - 2024-03-14 + +* [11.x] Revert collation change by [@driesvints](https://github.com/driesvints) in https://github.com/laravel/laravel/pull/6372 + +## [v11.0.2](https://github.com/laravel/laravel/compare/v11.0.1...v11.0.2) - 2024-03-13 + +* [11.x] Remove branch alias from composer.json by [@zepfietje](https://github.com/zepfietje) in https://github.com/laravel/laravel/pull/6366 +* [11.x] Fixes typo in welcome page by [@jrd-lewis](https://github.com/jrd-lewis) in https://github.com/laravel/laravel/pull/6363 +* change mariadb default by [@taylorotwell](https://github.com/taylorotwell) in https://github.com/laravel/laravel/commit/79969c99c6456a6d6edfbe78d241575fe1f65594 + +## [v11.0.1](https://github.com/laravel/laravel/compare/v11.0.0...v11.0.1) - 2024-03-12 + +* [11.x] Fixes SQLite driver missing by [@nunomaduro](https://github.com/nunomaduro) in https://github.com/laravel/laravel/pull/6361 + +## [v11.0.0 (2023-02-17)](https://github.com/laravel/laravel/compare/v10.3.2...v11.0.0) + +Laravel 11 includes a variety of changes to the application skeleton. Please consult the diff to see what's new. diff --git a/app/Http/Controllers/Auth/AuthenticatedSessionController.php b/app/Http/Controllers/Auth/AuthenticatedSessionController.php new file mode 100644 index 0000000..a33d282 --- /dev/null +++ b/app/Http/Controllers/Auth/AuthenticatedSessionController.php @@ -0,0 +1,38 @@ +authenticate(); + + $request->session()->regenerate(); + + return response()->noContent(); + } + + /** + * Destroy an authenticated session. + */ + public function destroy(Request $request): Response + { + Auth::guard('web')->logout(); + + $request->session()->invalidate(); + + $request->session()->regenerateToken(); + + return response()->noContent(); + } +} diff --git a/app/Http/Controllers/Auth/EmailVerificationNotificationController.php b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php new file mode 100644 index 0000000..0550fbd --- /dev/null +++ b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php @@ -0,0 +1,25 @@ +user()->hasVerifiedEmail()) { + return redirect()->intended('/dashboard'); + } + + $request->user()->sendEmailVerificationNotification(); + + return response()->json(['status' => 'verification-link-sent']); + } +} diff --git a/app/Http/Controllers/Auth/NewPasswordController.php b/app/Http/Controllers/Auth/NewPasswordController.php new file mode 100644 index 0000000..4277c32 --- /dev/null +++ b/app/Http/Controllers/Auth/NewPasswordController.php @@ -0,0 +1,53 @@ +validate([ + 'token' => ['required'], + 'email' => ['required', 'email'], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + ]); + + // Here we will attempt to reset the user's password. If it is successful we + // will update the password on an actual user model and persist it to the + // database. Otherwise we will parse the error and return the response. + $status = Password::reset( + $request->only('email', 'password', 'password_confirmation', 'token'), + function ($user) use ($request) { + $user->forceFill([ + 'password' => Hash::make($request->string('password')), + 'remember_token' => Str::random(60), + ])->save(); + + event(new PasswordReset($user)); + } + ); + + if ($status != Password::PASSWORD_RESET) { + throw ValidationException::withMessages([ + 'email' => [__($status)], + ]); + } + + return response()->json(['status' => __($status)]); + } +} diff --git a/app/Http/Controllers/Auth/PasswordResetLinkController.php b/app/Http/Controllers/Auth/PasswordResetLinkController.php new file mode 100644 index 0000000..95cde8e --- /dev/null +++ b/app/Http/Controllers/Auth/PasswordResetLinkController.php @@ -0,0 +1,39 @@ +validate([ + 'email' => ['required', 'email'], + ]); + + // We will send the password reset link to this user. Once we have attempted + // to send the link, we will examine the response then see the message we + // need to show to the user. Finally, we'll send out a proper response. + $status = Password::sendResetLink( + $request->only('email') + ); + + if ($status != Password::RESET_LINK_SENT) { + throw ValidationException::withMessages([ + 'email' => [__($status)], + ]); + } + + return response()->json(['status' => __($status)]); + } +} diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php new file mode 100644 index 0000000..c6edf9c --- /dev/null +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -0,0 +1,41 @@ +validate([ + 'name' => ['required', 'string', 'max:255'], + 'email' => ['required', 'string', 'lowercase', 'email', 'max:255', 'unique:'.User::class], + 'password' => ['required', 'confirmed', Rules\Password::defaults()], + ]); + + $user = User::create([ + 'name' => $request->name, + 'email' => $request->email, + 'password' => Hash::make($request->string('password')), + ]); + + event(new Registered($user)); + + Auth::login($user); + + return response()->noContent(); + } +} diff --git a/app/Http/Controllers/Auth/VerifyEmailController.php b/app/Http/Controllers/Auth/VerifyEmailController.php new file mode 100644 index 0000000..33cbed4 --- /dev/null +++ b/app/Http/Controllers/Auth/VerifyEmailController.php @@ -0,0 +1,31 @@ +user()->hasVerifiedEmail()) { + return redirect()->intended( + config('app.frontend_url').'/dashboard?verified=1' + ); + } + + if ($request->user()->markEmailAsVerified()) { + event(new Verified($request->user())); + } + + return redirect()->intended( + config('app.frontend_url').'/dashboard?verified=1' + ); + } +} diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php deleted file mode 100644 index 7ac5475..0000000 --- a/app/Http/Controllers/AuthController.php +++ /dev/null @@ -1,60 +0,0 @@ -validate([ - 'name' => 'required|max:255', - 'email' => 'required|email|max:255|unique:users', - 'password' => 'required|min:8|confirmed', - ]); - - $user = User::create($fields); - - $token = $user->createToken($request->name); - - return [ - 'user' => $user, - 'token' => $token - ]; - } - - public function login(Request $request) - { - $fields = $request->validate([ - 'email' => 'required|email|exists:users,email', - 'password' => 'required|min:8' - ]); - - $user = User::where('email', $request->email)->first(); - - if (!$user || !Hash::check($request->password, $user->password)) { - return response([ - 'message' => 'Bad creds' - ], 401); - } - - $token = $user->createToken($user->name); - - return [ - 'user' => $user, - 'token' => $token->plainTextToken - ]; - } - - public function logout(Request $request) - { - $request->user()->tokens()->delete(); - - return [ - 'message' => 'Logged out' - ]; - } -} diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php deleted file mode 100644 index 7d72d3f..0000000 --- a/app/Http/Controllers/CustomerController.php +++ /dev/null @@ -1,84 +0,0 @@ -json($customers); - } - - /** - * Store a newly created resource in storage. - */ - public function store(Request $request): JsonResponse - { - $validatedData = $request->validate([ - 'name' => 'required|string|max:100', - 'alamat' => 'required|string|max:255', - 'whatsapp' => 'required|string|max:15', - 'kategori' => 'required|string|max:50', - 'pekerjaan' => 'required|string|max:50', - 'bank' => 'required|string|max:50', - 'sertifikat' => 'required|string|max:50', - 'nilai_transaksi' => 'required|numeric', - 'harga_real' => 'required|numeric', - 'harga_kesepakatan' => 'required|numeric', - 'data_pajak_pembeli' => 'required|string|max:100', - 'data_pajak_penjual' => 'required|string|max:100', - ]); - - $customer = Customer::create($validatedData); - return response()->json($customer, 201); - } - - /** - * Display the specified resource. - */ - public function show(Customer $customer): JsonResponse - { - return response()->json($customer); - } - - /** - * Update the specified resource in storage. - */ - public function update(Request $request, Customer $customer): JsonResponse - { - $validatedData = $request->validate([ - 'name' => 'string|max:100', - 'alamat' => 'string|max:255', - 'whatsapp' => 'string|max:15', - 'kategori' => 'string|max:50', - 'pekerjaan' => 'string|max:50', - 'bank' => 'string|max:50', - 'sertifikat' => 'string|max:50', - 'nilai_transaksi' => 'numeric', - 'harga_real' => 'numeric', - 'harga_kesepakatan' => 'numeric', - 'data_pajak_pembeli' => 'string|max:100', - 'data_pajak_penjual' => 'string|max:100', - ]); - - $customer->update($validatedData); - return response()->json($customer); - } - - /** - * Remove the specified resource from storage. - */ - public function destroy(Customer $customer): JsonResponse - { - $customer->delete(); - return response()->json(null, 204); - } -} diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php deleted file mode 100644 index 5bceec4..0000000 --- a/app/Http/Controllers/PostController.php +++ /dev/null @@ -1,79 +0,0 @@ -validate([ - 'title' => 'required|max:255', - 'body' => 'required', - ]); - - $post = $request->user()->posts()->create($fdields); - - return $post; - } - - /** - * Display the specified resource. - */ - public function show(Post $post) - { - return $post; - } - - /** - * Update the specified resource in storage. - */ - public function update(Request $request, Post $post) - { - Gate::authorize('modify', $post); - - $fdields = $request->validate([ - 'title' => 'required|max:255', - 'body' => 'required', - ]); - - $post->update($fdields); - - return $post; - } - - /** - * Remove the specified resource from storage. - */ - public function destroy(Post $post) - { - Gate::authorize('modify', $post); - $post->delete(); - - return ['message' => 'Post Deleted']; - } -} diff --git a/app/Http/Middleware/EnsureEmailIsVerified.php b/app/Http/Middleware/EnsureEmailIsVerified.php new file mode 100644 index 0000000..f562059 --- /dev/null +++ b/app/Http/Middleware/EnsureEmailIsVerified.php @@ -0,0 +1,27 @@ +user() || + ($request->user() instanceof MustVerifyEmail && + ! $request->user()->hasVerifiedEmail())) { + return response()->json(['message' => 'Your email address is not verified.'], 409); + } + + return $next($request); + } +} diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php new file mode 100644 index 0000000..4d3637a --- /dev/null +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -0,0 +1,85 @@ + + */ + public function rules(): array + { + return [ + 'email' => ['required', 'string', 'email'], + 'password' => ['required', 'string'], + ]; + } + + /** + * Attempt to authenticate the request's credentials. + * + * @throws \Illuminate\Validation\ValidationException + */ + public function authenticate(): void + { + $this->ensureIsNotRateLimited(); + + if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) { + RateLimiter::hit($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => __('auth.failed'), + ]); + } + + RateLimiter::clear($this->throttleKey()); + } + + /** + * Ensure the login request is not rate limited. + * + * @throws \Illuminate\Validation\ValidationException + */ + public function ensureIsNotRateLimited(): void + { + if (! RateLimiter::tooManyAttempts($this->throttleKey(), 5)) { + return; + } + + event(new Lockout($this)); + + $seconds = RateLimiter::availableIn($this->throttleKey()); + + throw ValidationException::withMessages([ + 'email' => trans('auth.throttle', [ + 'seconds' => $seconds, + 'minutes' => ceil($seconds / 60), + ]), + ]); + } + + /** + * Get the rate limiting throttle key for the request. + */ + public function throttleKey(): string + { + return Str::transliterate(Str::lower($this->input('email')).'|'.$this->ip()); + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php deleted file mode 100644 index 2af26c4..0000000 --- a/app/Models/Customer.php +++ /dev/null @@ -1,27 +0,0 @@ -belongsTo(User::class); - } -} diff --git a/app/Models/User.php b/app/Models/User.php index eb406d8..3dfbd80 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,11 +6,11 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; -use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { - use HasFactory, Notifiable, HasApiTokens; + /** @use HasFactory<\Database\Factories\UserFactory> */ + use HasFactory, Notifiable; /** * The attributes that are mass assignable. @@ -45,9 +45,4 @@ protected function casts(): array 'password' => 'hashed', ]; } - - public function posts() - { - return $this->hasMany(Post::class); - } } diff --git a/app/Policies/PostPolicy.php b/app/Policies/PostPolicy.php deleted file mode 100644 index e45299d..0000000 --- a/app/Policies/PostPolicy.php +++ /dev/null @@ -1,20 +0,0 @@ -id === $post->user_id - ? Response::allow() - : Response::deny('You can only modify your own posts.'); - } -} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 452e6b6..96ddc37 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,6 +2,7 @@ namespace App\Providers; +use Illuminate\Auth\Notifications\ResetPassword; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider @@ -19,6 +20,8 @@ public function register(): void */ public function boot(): void { - // + ResetPassword::createUrlUsing(function (object $notifiable, string $token) { + return config('app.frontend_url')."/password-reset/$token?email={$notifiable->getEmailForPasswordReset()}"; + }); } } diff --git a/bootstrap/app.php b/bootstrap/app.php index d654276..e7e7bdb 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -12,6 +12,14 @@ health: '/up', ) ->withMiddleware(function (Middleware $middleware) { + $middleware->api(prepend: [ + \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, + ]); + + $middleware->alias([ + 'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class, + ]); + // }) ->withExceptions(function (Exceptions $exceptions) { diff --git a/composer.json b/composer.json index 2a656a1..87d5460 100644 --- a/composer.json +++ b/composer.json @@ -12,10 +12,12 @@ }, "require-dev": { "fakerphp/faker": "^1.23", + "laravel/breeze": "^2.2", + "laravel/pail": "^1.1", "laravel/pint": "^1.13", "laravel/sail": "^1.26", "mockery/mockery": "^1.6", - "nunomaduro/collision": "^8.0", + "nunomaduro/collision": "^8.1", "phpunit/phpunit": "^11.0.1" }, "autoload": { @@ -45,6 +47,10 @@ "@php artisan key:generate --ansi", "@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"", "@php artisan migrate --graceful --ansi" + ], + "dev": [ + "Composer\\Config::disableProcessTimeout", + "npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite" ] }, "extra": { diff --git a/composer.lock b/composer.lock index 3fe5e0f..b755063 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "eba04bbb24b3180d2a6614993a886c4b", + "content-hash": "785aaa5464fc438ca2615f92095171f0", "packages": [ { "name": "brick/math", @@ -380,16 +380,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.3", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", - "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { @@ -402,10 +402,14 @@ "require-dev": { "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", - "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -429,7 +433,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, "funding": [ { @@ -437,7 +441,7 @@ "type": "github" } ], - "time": "2023-08-10T19:36:49+00:00" + "time": "2024-10-09T13:47:03+00:00" }, { "name": "egulias/email-validator", @@ -767,16 +771,16 @@ }, { "name": "guzzlehttp/promises", - "version": "2.0.3", + "version": "2.0.4", "source": { "type": "git", "url": "https://github.com/guzzle/promises.git", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8" + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", - "reference": "6ea8dd08867a2a42619d65c3deb2c0fcbf81c8f8", + "url": "https://api.github.com/repos/guzzle/promises/zipball/f9c436286ab2892c7db7be8c8da4ef61ccf7b455", + "reference": "f9c436286ab2892c7db7be8c8da4ef61ccf7b455", "shasum": "" }, "require": { @@ -830,7 +834,7 @@ ], "support": { "issues": "https://github.com/guzzle/promises/issues", - "source": "https://github.com/guzzle/promises/tree/2.0.3" + "source": "https://github.com/guzzle/promises/tree/2.0.4" }, "funding": [ { @@ -846,7 +850,7 @@ "type": "tidelift" } ], - "time": "2024-07-18T10:29:17+00:00" + "time": "2024-10-17T10:06:22+00:00" }, { "name": "guzzlehttp/psr7", @@ -1052,16 +1056,16 @@ }, { "name": "laravel/framework", - "version": "v11.26.0", + "version": "v11.30.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "b8cb8998701d5b3cfe68539d3c3da1fc59ddd82b" + "reference": "dff716442d9c229d716be82ccc9a7de52eb97193" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/b8cb8998701d5b3cfe68539d3c3da1fc59ddd82b", - "reference": "b8cb8998701d5b3cfe68539d3c3da1fc59ddd82b", + "url": "https://api.github.com/repos/laravel/framework/zipball/dff716442d9c229d716be82ccc9a7de52eb97193", + "reference": "dff716442d9c229d716be82ccc9a7de52eb97193", "shasum": "" }, "require": { @@ -1257,20 +1261,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-10-01T14:29:34+00:00" + "time": "2024-10-30T15:00:34+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.0", + "version": "v0.3.1", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "ea57a2261093986721d4a5f4f9524d76f21f9fa0" + "reference": "0f3848a445562dac376b27968f753c65e7e1036e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/ea57a2261093986721d4a5f4f9524d76f21f9fa0", - "reference": "ea57a2261093986721d4a5f4f9524d76f21f9fa0", + "url": "https://api.github.com/repos/laravel/prompts/zipball/0f3848a445562dac376b27968f753c65e7e1036e", + "reference": "0f3848a445562dac376b27968f753c65e7e1036e", "shasum": "" }, "require": { @@ -1314,9 +1318,9 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.0" + "source": "https://github.com/laravel/prompts/tree/v0.3.1" }, - "time": "2024-09-30T14:27:51+00:00" + "time": "2024-10-09T19:42:26+00:00" }, { "name": "laravel/sanctum", @@ -1699,16 +1703,16 @@ }, { "name": "league/flysystem", - "version": "3.29.0", + "version": "3.29.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "0adc0d9a51852e170e0028a60bd271726626d3f0" + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/0adc0d9a51852e170e0028a60bd271726626d3f0", - "reference": "0adc0d9a51852e170e0028a60bd271726626d3f0", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/edc1bb7c86fab0776c3287dbd19b5fa278347319", + "reference": "edc1bb7c86fab0776c3287dbd19b5fa278347319", "shasum": "" }, "require": { @@ -1776,9 +1780,9 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.29.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.29.1" }, - "time": "2024-09-29T11:59:11+00:00" + "time": "2024-10-08T08:58:34+00:00" }, { "name": "league/flysystem-local", @@ -2094,24 +2098,24 @@ }, { "name": "nette/schema", - "version": "v1.3.0", + "version": "v1.3.2", "source": { "type": "git", "url": "https://github.com/nette/schema.git", - "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188" + "reference": "da801d52f0354f70a638673c4a0f04e16529431d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/schema/zipball/a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", - "reference": "a6d3a6d1f545f01ef38e60f375d1cf1f4de98188", + "url": "https://api.github.com/repos/nette/schema/zipball/da801d52f0354f70a638673c4a0f04e16529431d", + "reference": "da801d52f0354f70a638673c4a0f04e16529431d", "shasum": "" }, "require": { "nette/utils": "^4.0", - "php": "8.1 - 8.3" + "php": "8.1 - 8.4" }, "require-dev": { - "nette/tester": "^2.4", + "nette/tester": "^2.5.2", "phpstan/phpstan-nette": "^1.0", "tracy/tracy": "^2.8" }, @@ -2150,9 +2154,9 @@ ], "support": { "issues": "https://github.com/nette/schema/issues", - "source": "https://github.com/nette/schema/tree/v1.3.0" + "source": "https://github.com/nette/schema/tree/v1.3.2" }, - "time": "2023-12-11T11:54:22+00:00" + "time": "2024-10-06T23:10:23+00:00" }, { "name": "nette/utils", @@ -2242,16 +2246,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.3.0", + "version": "v5.3.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a" + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3abf7425cd284141dc5d8d14a9ee444de3345d1a", - "reference": "3abf7425cd284141dc5d8d14a9ee444de3345d1a", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", + "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", "shasum": "" }, "require": { @@ -2294,38 +2298,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" }, - "time": "2024-09-29T13:56:26+00:00" + "time": "2024-10-08T18:51:32+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "e5f21eade88689536c0cdad4c3cd75f3ed26e01a" + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/e5f21eade88689536c0cdad4c3cd75f3ed26e01a", - "reference": "e5f21eade88689536c0cdad4c3cd75f3ed26e01a", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/42c84e4e8090766bbd6445d06cd6e57650626ea3", + "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.0.4" + "symfony/console": "^7.1.5" }, "require-dev": { - "ergebnis/phpstan-rules": "^2.2.0", - "illuminate/console": "^11.1.1", - "laravel/pint": "^1.15.0", - "mockery/mockery": "^1.6.11", - "pestphp/pest": "^2.34.6", - "phpstan/phpstan": "^1.10.66", - "phpstan/phpstan-strict-rules": "^1.5.2", - "symfony/var-dumper": "^7.0.4", + "illuminate/console": "^11.28.0", + "laravel/pint": "^1.18.1", + "mockery/mockery": "^1.6.12", + "pestphp/pest": "^2.36.0", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-strict-rules": "^1.6.1", + "symfony/var-dumper": "^7.1.5", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -2368,7 +2371,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.1.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.2.0" }, "funding": [ { @@ -2384,7 +2387,7 @@ "type": "github" } ], - "time": "2024-09-05T15:25:50+00:00" + "time": "2024-10-15T16:15:16+00:00" }, { "name": "phpoption/phpoption", @@ -3179,16 +3182,16 @@ }, { "name": "symfony/clock", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "3dfc8b084853586de51dd1441c6242c76a28cbe7" + "reference": "97bebc53548684c17ed696bc8af016880f0f098d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/3dfc8b084853586de51dd1441c6242c76a28cbe7", - "reference": "3dfc8b084853586de51dd1441c6242c76a28cbe7", + "url": "https://api.github.com/repos/symfony/clock/zipball/97bebc53548684c17ed696bc8af016880f0f098d", + "reference": "97bebc53548684c17ed696bc8af016880f0f098d", "shasum": "" }, "require": { @@ -3233,7 +3236,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.1.1" + "source": "https://github.com/symfony/clock/tree/v7.1.6" }, "funding": [ { @@ -3249,20 +3252,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/console", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee" + "reference": "bb5192af6edc797cbab5c8e8ecfea2fe5f421e57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0fa539d12b3ccf068a722bbbffa07ca7079af9ee", - "reference": "0fa539d12b3ccf068a722bbbffa07ca7079af9ee", + "url": "https://api.github.com/repos/symfony/console/zipball/bb5192af6edc797cbab5c8e8ecfea2fe5f421e57", + "reference": "bb5192af6edc797cbab5c8e8ecfea2fe5f421e57", "shasum": "" }, "require": { @@ -3326,7 +3329,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.5" + "source": "https://github.com/symfony/console/tree/v7.1.6" }, "funding": [ { @@ -3342,20 +3345,20 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:28:38+00:00" + "time": "2024-10-09T08:46:59+00:00" }, { "name": "symfony/css-selector", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "1c7cee86c6f812896af54434f8ce29c8d94f9ff4" + "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/1c7cee86c6f812896af54434f8ce29c8d94f9ff4", - "reference": "1c7cee86c6f812896af54434f8ce29c8d94f9ff4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", + "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", "shasum": "" }, "require": { @@ -3391,7 +3394,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.1.1" + "source": "https://github.com/symfony/css-selector/tree/v7.1.6" }, "funding": [ { @@ -3407,7 +3410,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/deprecation-contracts", @@ -3478,16 +3481,16 @@ }, { "name": "symfony/error-handler", - "version": "v7.1.3", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "432bb369952795c61ca1def65e078c4a80dad13c" + "reference": "d60117093c2a9fe667baa8fedf84e8a09b9c592f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/432bb369952795c61ca1def65e078c4a80dad13c", - "reference": "432bb369952795c61ca1def65e078c4a80dad13c", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/d60117093c2a9fe667baa8fedf84e8a09b9c592f", + "reference": "d60117093c2a9fe667baa8fedf84e8a09b9c592f", "shasum": "" }, "require": { @@ -3533,7 +3536,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.1.3" + "source": "https://github.com/symfony/error-handler/tree/v7.1.6" }, "funding": [ { @@ -3549,20 +3552,20 @@ "type": "tidelift" } ], - "time": "2024-07-26T13:02:51+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.1.1", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7" + "reference": "87254c78dd50721cfd015b62277a8281c5589702" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", - "reference": "9fa7f7a21beb22a39a8f3f28618b29e50d7a55a7", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87254c78dd50721cfd015b62277a8281c5589702", + "reference": "87254c78dd50721cfd015b62277a8281c5589702", "shasum": "" }, "require": { @@ -3613,7 +3616,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.1" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.6" }, "funding": [ { @@ -3629,7 +3632,7 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:57:53+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -3709,16 +3712,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", "shasum": "" }, "require": { @@ -3753,7 +3756,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.4" + "source": "https://github.com/symfony/finder/tree/v7.1.6" }, "funding": [ { @@ -3769,20 +3772,20 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e30ef73b1e44eea7eb37ba69600a354e553f694b" + "reference": "3d7bbf071b25f802f7d55524d408bed414ea71e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e30ef73b1e44eea7eb37ba69600a354e553f694b", - "reference": "e30ef73b1e44eea7eb37ba69600a354e553f694b", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3d7bbf071b25f802f7d55524d408bed414ea71e2", + "reference": "3d7bbf071b25f802f7d55524d408bed414ea71e2", "shasum": "" }, "require": { @@ -3830,7 +3833,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.1.5" + "source": "https://github.com/symfony/http-foundation/tree/v7.1.6" }, "funding": [ { @@ -3846,20 +3849,20 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:28:38+00:00" + "time": "2024-10-11T19:23:14+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "44204d96150a9df1fc57601ec933d23fefc2d65b" + "reference": "5d8315899cd76b2e7e29179bf5fea103e41bdf03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/44204d96150a9df1fc57601ec933d23fefc2d65b", - "reference": "44204d96150a9df1fc57601ec933d23fefc2d65b", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/5d8315899cd76b2e7e29179bf5fea103e41bdf03", + "reference": "5d8315899cd76b2e7e29179bf5fea103e41bdf03", "shasum": "" }, "require": { @@ -3944,7 +3947,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.5" + "source": "https://github.com/symfony/http-kernel/tree/v7.1.6" }, "funding": [ { @@ -3960,20 +3963,20 @@ "type": "tidelift" } ], - "time": "2024-09-21T06:09:21+00:00" + "time": "2024-10-27T13:54:21+00:00" }, { "name": "symfony/mailer", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "bbf21460c56f29810da3df3e206e38dfbb01e80b" + "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/bbf21460c56f29810da3df3e206e38dfbb01e80b", - "reference": "bbf21460c56f29810da3df3e206e38dfbb01e80b", + "url": "https://api.github.com/repos/symfony/mailer/zipball/69c9948451fb3a6a4d47dc8261d1794734e76cdd", + "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd", "shasum": "" }, "require": { @@ -4024,7 +4027,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.1.5" + "source": "https://github.com/symfony/mailer/tree/v7.1.6" }, "funding": [ { @@ -4040,20 +4043,20 @@ "type": "tidelift" } ], - "time": "2024-09-08T12:32:26+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/mime", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff" + "reference": "caa1e521edb2650b8470918dfe51708c237f0598" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/711d2e167e8ce65b05aea6b258c449671cdd38ff", - "reference": "711d2e167e8ce65b05aea6b258c449671cdd38ff", + "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", + "reference": "caa1e521edb2650b8470918dfe51708c237f0598", "shasum": "" }, "require": { @@ -4108,7 +4111,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.5" + "source": "https://github.com/symfony/mime/tree/v7.1.6" }, "funding": [ { @@ -4124,7 +4127,7 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:28:38+00:00" + "time": "2024-10-25T15:11:02+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4764,16 +4767,16 @@ }, { "name": "symfony/process", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5c03ee6369281177f07f7c68252a280beccba847" + "reference": "6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847", - "reference": "5c03ee6369281177f07f7c68252a280beccba847", + "url": "https://api.github.com/repos/symfony/process/zipball/6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e", + "reference": "6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e", "shasum": "" }, "require": { @@ -4805,7 +4808,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.5" + "source": "https://github.com/symfony/process/tree/v7.1.6" }, "funding": [ { @@ -4821,20 +4824,20 @@ "type": "tidelift" } ], - "time": "2024-09-19T21:48:23+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/routing", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7" + "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", - "reference": "1500aee0094a3ce1c92626ed8cf3c2037e86f5a7", + "url": "https://api.github.com/repos/symfony/routing/zipball/66a2c469f6c22d08603235c46a20007c0701ea0a", + "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a", "shasum": "" }, "require": { @@ -4886,7 +4889,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.4" + "source": "https://github.com/symfony/routing/tree/v7.1.6" }, "funding": [ { @@ -4902,7 +4905,7 @@ "type": "tidelift" } ], - "time": "2024-08-29T08:16:25+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/service-contracts", @@ -4989,16 +4992,16 @@ }, { "name": "symfony/string", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" + "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", - "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", + "url": "https://api.github.com/repos/symfony/string/zipball/61b72d66bf96c360a727ae6232df5ac83c71f626", + "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626", "shasum": "" }, "require": { @@ -5056,7 +5059,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.5" + "source": "https://github.com/symfony/string/tree/v7.1.6" }, "funding": [ { @@ -5072,20 +5075,20 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:28:38+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/translation", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "235535e3f84f3dfbdbde0208ede6ca75c3a489ea" + "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/235535e3f84f3dfbdbde0208ede6ca75c3a489ea", - "reference": "235535e3f84f3dfbdbde0208ede6ca75c3a489ea", + "url": "https://api.github.com/repos/symfony/translation/zipball/b9f72ab14efdb6b772f85041fa12f820dee8d55f", + "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f", "shasum": "" }, "require": { @@ -5150,7 +5153,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.1.5" + "source": "https://github.com/symfony/translation/tree/v7.1.6" }, "funding": [ { @@ -5166,7 +5169,7 @@ "type": "tidelift" } ], - "time": "2024-09-16T06:30:38+00:00" + "time": "2024-09-28T12:35:13+00:00" }, { "name": "symfony/translation-contracts", @@ -5248,16 +5251,16 @@ }, { "name": "symfony/uid", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "8c7bb8acb933964055215d89f9a9871df0239317" + "reference": "65befb3bb2d503bbffbd08c815aa38b472999917" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/8c7bb8acb933964055215d89f9a9871df0239317", - "reference": "8c7bb8acb933964055215d89f9a9871df0239317", + "url": "https://api.github.com/repos/symfony/uid/zipball/65befb3bb2d503bbffbd08c815aa38b472999917", + "reference": "65befb3bb2d503bbffbd08c815aa38b472999917", "shasum": "" }, "require": { @@ -5302,7 +5305,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.5" + "source": "https://github.com/symfony/uid/tree/v7.1.6" }, "funding": [ { @@ -5318,20 +5321,20 @@ "type": "tidelift" } ], - "time": "2024-09-17T09:16:35+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "e20e03889539fd4e4211e14d2179226c513c010d" + "reference": "cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e20e03889539fd4e4211e14d2179226c513c010d", - "reference": "e20e03889539fd4e4211e14d2179226c513c010d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c", + "reference": "cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c", "shasum": "" }, "require": { @@ -5385,7 +5388,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.5" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.6" }, "funding": [ { @@ -5401,7 +5404,7 @@ "type": "tidelift" } ], - "time": "2024-09-16T10:07:02+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -5859,6 +5862,143 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "laravel/breeze", + "version": "v2.2.4", + "source": { + "type": "git", + "url": "https://github.com/laravel/breeze.git", + "reference": "d3484d08aaaa84896bdd2d1787e7da0fc03f676f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/breeze/zipball/d3484d08aaaa84896bdd2d1787e7da0fc03f676f", + "reference": "d3484d08aaaa84896bdd2d1787e7da0fc03f676f", + "shasum": "" + }, + "require": { + "illuminate/console": "^11.0", + "illuminate/filesystem": "^11.0", + "illuminate/support": "^11.0", + "illuminate/validation": "^11.0", + "php": "^8.2.0", + "symfony/console": "^7.0" + }, + "require-dev": { + "orchestra/testbench": "^9.0", + "phpstan/phpstan": "^1.10" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Laravel\\Breeze\\BreezeServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Breeze\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Minimal Laravel authentication scaffolding with Blade and Tailwind.", + "keywords": [ + "auth", + "laravel" + ], + "support": { + "issues": "https://github.com/laravel/breeze/issues", + "source": "https://github.com/laravel/breeze" + }, + "time": "2024-10-29T15:11:57+00:00" + }, + { + "name": "laravel/pail", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/pail.git", + "reference": "085a2306b520c3896afa361c25704e5fa3c27bf0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/pail/zipball/085a2306b520c3896afa361c25704e5fa3c27bf0", + "reference": "085a2306b520c3896afa361c25704e5fa3c27bf0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "illuminate/console": "^10.24|^11.0", + "illuminate/contracts": "^10.24|^11.0", + "illuminate/log": "^10.24|^11.0", + "illuminate/process": "^10.24|^11.0", + "illuminate/support": "^10.24|^11.0", + "nunomaduro/termwind": "^1.15|^2.0", + "php": "^8.2", + "symfony/console": "^6.0|^7.0" + }, + "require-dev": { + "laravel/pint": "^1.13", + "orchestra/testbench": "^8.12|^9.0", + "pestphp/pest": "^2.20", + "pestphp/pest-plugin-type-coverage": "^2.3", + "phpstan/phpstan": "^1.10", + "symfony/var-dumper": "^6.3|^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Pail\\PailServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Pail\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Easily delve into your Laravel application's log files directly from the command line.", + "homepage": "https://github.com/laravel/pail", + "keywords": [ + "laravel", + "logs", + "php", + "tail" + ], + "support": { + "issues": "https://github.com/laravel/pail/issues", + "source": "https://github.com/laravel/pail" + }, + "time": "2024-10-21T13:59:30+00:00" + }, { "name": "laravel/pint", "version": "v1.18.1", @@ -5927,16 +6067,16 @@ }, { "name": "laravel/sail", - "version": "v1.34.0", + "version": "v1.37.1", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "511e9c95b0f3ee778dc9e11e242bcd2af8e002cd" + "reference": "7efa151ea0d16f48233d6a6cd69f81270acc6e93" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/511e9c95b0f3ee778dc9e11e242bcd2af8e002cd", - "reference": "511e9c95b0f3ee778dc9e11e242bcd2af8e002cd", + "url": "https://api.github.com/repos/laravel/sail/zipball/7efa151ea0d16f48233d6a6cd69f81270acc6e93", + "reference": "7efa151ea0d16f48233d6a6cd69f81270acc6e93", "shasum": "" }, "require": { @@ -5986,7 +6126,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2024-09-27T14:58:09+00:00" + "time": "2024-10-29T20:18:14+00:00" }, { "name": "mockery/mockery", @@ -6133,23 +6273,23 @@ }, { "name": "nunomaduro/collision", - "version": "v8.4.0", + "version": "v8.5.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a" + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/e7d1aa8ed753f63fa816932bbc89678238843b4a", - "reference": "e7d1aa8ed753f63fa816932bbc89678238843b4a", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", "shasum": "" }, "require": { - "filp/whoops": "^2.15.4", - "nunomaduro/termwind": "^2.0.1", + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", "php": "^8.2.0", - "symfony/console": "^7.1.3" + "symfony/console": "^7.1.5" }, "conflict": { "laravel/framework": "<11.0.0 || >=12.0.0", @@ -6157,14 +6297,14 @@ }, "require-dev": { "larastan/larastan": "^2.9.8", - "laravel/framework": "^11.19.0", - "laravel/pint": "^1.17.1", - "laravel/sail": "^1.31.0", - "laravel/sanctum": "^4.0.2", - "laravel/tinker": "^2.9.0", - "orchestra/testbench-core": "^9.2.3", - "pestphp/pest": "^2.35.0 || ^3.0.0", - "sebastian/environment": "^6.1.0 || ^7.0.0" + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", "extra": { @@ -6226,7 +6366,7 @@ "type": "patreon" } ], - "time": "2024-08-03T15:32:23+00:00" + "time": "2024-10-15T16:06:32+00:00" }, { "name": "phar-io/manifest", @@ -6348,35 +6488,35 @@ }, { "name": "phpunit/php-code-coverage", - "version": "11.0.6", + "version": "11.0.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45" + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ebdffc9e09585dafa71b9bffcdb0a229d4704c45", - "reference": "ebdffc9e09585dafa71b9bffcdb0a229d4704c45", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", "ext-xmlwriter": "*", - "nikic/php-parser": "^5.1.0", + "nikic/php-parser": "^5.3.1", "php": ">=8.2", - "phpunit/php-file-iterator": "^5.0.1", + "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-text-template": "^4.0.1", "sebastian/code-unit-reverse-lookup": "^4.0.1", "sebastian/complexity": "^4.0.1", "sebastian/environment": "^7.2.0", "sebastian/lines-of-code": "^3.0.1", - "sebastian/version": "^5.0.1", + "sebastian/version": "^5.0.2", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.4.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -6414,7 +6554,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.6" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" }, "funding": [ { @@ -6422,7 +6562,7 @@ "type": "github" } ], - "time": "2024-08-22T04:37:56+00:00" + "time": "2024-10-09T06:21:38+00:00" }, { "name": "phpunit/php-file-iterator", @@ -6671,16 +6811,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.3.6", + "version": "11.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d62c45a19c665bb872c2a47023a0baf41a98bb2b" + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d62c45a19c665bb872c2a47023a0baf41a98bb2b", - "reference": "d62c45a19c665bb872c2a47023a0baf41a98bb2b", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", + "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", "shasum": "" }, "require": { @@ -6694,21 +6834,21 @@ "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.6", + "phpunit/php-code-coverage": "^11.0.7", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", "sebastian/code-unit": "^3.0.1", - "sebastian/comparator": "^6.1.0", + "sebastian/comparator": "^6.1.1", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", "sebastian/exporter": "^6.1.3", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", "sebastian/type": "^5.1.0", - "sebastian/version": "^5.0.1" + "sebastian/version": "^5.0.2" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -6719,7 +6859,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "11.3-dev" + "dev-main": "11.4-dev" } }, "autoload": { @@ -6751,7 +6891,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.3.6" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" }, "funding": [ { @@ -6767,7 +6907,7 @@ "type": "tidelift" } ], - "time": "2024-09-19T10:54:28+00:00" + "time": "2024-10-28T13:07:50+00:00" }, { "name": "sebastian/cli-parser", @@ -6941,16 +7081,16 @@ }, { "name": "sebastian/comparator", - "version": "6.1.0", + "version": "6.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d" + "reference": "df95a6e827808debe3dbe190022dd0f643d5d909" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa37b9e2ca618cb051d71b60120952ee8ca8b03d", - "reference": "fa37b9e2ca618cb051d71b60120952ee8ca8b03d", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/df95a6e827808debe3dbe190022dd0f643d5d909", + "reference": "df95a6e827808debe3dbe190022dd0f643d5d909", "shasum": "" }, "require": { @@ -6961,12 +7101,12 @@ "sebastian/exporter": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.3" + "phpunit/phpunit": "^11.4" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "6.1-dev" + "dev-main": "6.2-dev" } }, "autoload": { @@ -7006,7 +7146,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.1.0" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.0" }, "funding": [ { @@ -7014,7 +7154,7 @@ "type": "github" } ], - "time": "2024-09-11T15:42:56+00:00" + "time": "2024-10-30T13:12:44+00:00" }, { "name": "sebastian/complexity", @@ -7640,16 +7780,16 @@ }, { "name": "sebastian/version", - "version": "5.0.1", + "version": "5.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4" + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/45c9debb7d039ce9b97de2f749c2cf5832a06ac4", - "reference": "45c9debb7d039ce9b97de2f749c2cf5832a06ac4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c687e3387b99f5b03b6caa64c74b63e2936ff874", + "reference": "c687e3387b99f5b03b6caa64c74b63e2936ff874", "shasum": "" }, "require": { @@ -7682,7 +7822,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/version/issues", "security": "https://github.com/sebastianbergmann/version/security/policy", - "source": "https://github.com/sebastianbergmann/version/tree/5.0.1" + "source": "https://github.com/sebastianbergmann/version/tree/5.0.2" }, "funding": [ { @@ -7690,20 +7830,20 @@ "type": "github" } ], - "time": "2024-07-03T05:13:08+00:00" + "time": "2024-10-09T05:16:32+00:00" }, { "name": "symfony/yaml", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "4e561c316e135e053bd758bf3b3eb291d9919de4" + "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/4e561c316e135e053bd758bf3b3eb291d9919de4", - "reference": "4e561c316e135e053bd758bf3b3eb291d9919de4", + "url": "https://api.github.com/repos/symfony/yaml/zipball/3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", + "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", "shasum": "" }, "require": { @@ -7745,7 +7885,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.1.5" + "source": "https://github.com/symfony/yaml/tree/v7.1.6" }, "funding": [ { @@ -7761,7 +7901,7 @@ "type": "tidelift" } ], - "time": "2024-09-17T12:49:58+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "theseer/tokenizer", @@ -7816,12 +7956,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": [], + "platform-dev": {}, "plugin-api-version": "2.6.0" } diff --git a/config/cors.php b/config/cors.php new file mode 100644 index 0000000..f2bf88b --- /dev/null +++ b/config/cors.php @@ -0,0 +1,34 @@ + ['*'], + + 'allowed_methods' => ['*'], + + 'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], + + 'allowed_origins_patterns' => [], + + 'allowed_headers' => ['*'], + + 'exposed_headers' => [], + + 'max_age' => 0, + + 'supports_credentials' => true, + +]; diff --git a/config/sanctum.php b/config/sanctum.php index 764a82f..b03f249 100644 --- a/config/sanctum.php +++ b/config/sanctum.php @@ -16,9 +16,10 @@ */ 'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf( - '%s%s', - 'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1', - Sanctum::currentApplicationUrlWithPort() + '%s%s%s', + 'localhost,localhost:3000,127.0.0.1,127.0.0.1:3000,127.0.0.1:8000,::1', + Sanctum::currentApplicationUrlWithPort(), + env('FRONTEND_URL') ? ','.parse_url(env('FRONTEND_URL'), PHP_URL_HOST) : '' ))), /* diff --git a/database/factories/PostFactory.php b/database/factories/PostFactory.php deleted file mode 100644 index 55f1633..0000000 --- a/database/factories/PostFactory.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -class PostFactory extends Factory -{ - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - // - ]; - } -} diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php new file mode 100644 index 0000000..425e705 --- /dev/null +++ b/database/migrations/0001_01_01_000002_create_jobs_table.php @@ -0,0 +1,57 @@ +id(); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + }); + + Schema::create('job_batches', function (Blueprint $table) { + $table->string('id')->primary(); + $table->string('name'); + $table->integer('total_jobs'); + $table->integer('pending_jobs'); + $table->integer('failed_jobs'); + $table->longText('failed_job_ids'); + $table->mediumText('options')->nullable(); + $table->integer('cancelled_at')->nullable(); + $table->integer('created_at'); + $table->integer('finished_at')->nullable(); + }); + + Schema::create('failed_jobs', function (Blueprint $table) { + $table->id(); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('jobs'); + Schema::dropIfExists('job_batches'); + Schema::dropIfExists('failed_jobs'); + } +}; diff --git a/database/migrations/2024_10_29_003420_create_customers_table.php b/database/migrations/2024_10_29_003420_create_customers_table.php deleted file mode 100644 index a6aca02..0000000 --- a/database/migrations/2024_10_29_003420_create_customers_table.php +++ /dev/null @@ -1,39 +0,0 @@ -id(); - $table->string('name', 100); - $table->string('alamat', 255); - $table->string('whatsapp', 15); - $table->string('kategori', 50); - $table->string('pekerjaan', 50); - $table->string('bank', 50); - $table->string('sertifikat', 50); - $table->decimal('nilai_transaksi', 15, 2); - $table->decimal('harga_real', 15, 2); - $table->decimal('harga_kesepakatan', 15, 2); - $table->string('data_pajak_pembeli', 100); - $table->string('data_pajak_penjual', 100); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - */ - public function down(): void - { - Schema::dropIfExists('customers'); - } -}; diff --git a/database/migrations/2024_10_03_022302_create_personal_access_tokens_table.php b/database/migrations/2024_10_31_042843_create_personal_access_tokens_table.php similarity index 100% rename from database/migrations/2024_10_03_022302_create_personal_access_tokens_table.php rename to database/migrations/2024_10_31_042843_create_personal_access_tokens_table.php diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php deleted file mode 100644 index 7f8bfe7..0000000 --- a/database/seeders/CustomerSeeder.php +++ /dev/null @@ -1,37 +0,0 @@ -insert([ - 'name' => $faker->name, - 'alamat' => $faker->address, - 'whatsapp' => $faker->phoneNumber, - 'kategori' => $faker->word, - 'pekerjaan' => $faker->jobTitle, - 'bank' => $faker->company, - 'sertifikat' => $faker->word, - 'nilai_transaksi' => $faker->randomFloat(2, 1000, 100000), // random float between 1000 and 100000 - 'harga_real' => $faker->randomFloat(2, 1000, 100000), - 'harga_kesepakatan' => $faker->randomFloat(2, 1000, 100000), - 'data_pajak_pembeli' => $faker->word, - 'data_pajak_penjual' => $faker->word, - 'created_at' => now(), - 'updated_at' => now(), - ]); - } - } -} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 91ed73b..d01a0ef 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -13,12 +13,11 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - User::factory()->count(10)->create(); + // User::factory(10)->create(); + User::factory()->create([ 'name' => 'Test User', 'email' => 'test@example.com', - 'password' => bcrypt('password'), ]); - $this->call(CustomerSeeder::class); } } diff --git a/package.json b/package.json deleted file mode 100644 index 5d67800..0000000 --- a/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build" - }, - "devDependencies": { - "axios": "^1.7.4", - "laravel-vite-plugin": "^1.0", - "vite": "^5.0" - } -} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..49c0612 --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/resources/css/app.css b/resources/css/app.css deleted file mode 100644 index e69de29..0000000 diff --git a/resources/js/app.js b/resources/js/app.js deleted file mode 100644 index e59d6a0..0000000 --- a/resources/js/app.js +++ /dev/null @@ -1 +0,0 @@ -import './bootstrap'; diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js deleted file mode 100644 index 5f1390b..0000000 --- a/resources/js/bootstrap.js +++ /dev/null @@ -1,4 +0,0 @@ -import axios from 'axios'; -window.axios = axios; - -window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; diff --git a/resources/views/.gitkeep b/resources/views/.gitkeep new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/resources/views/.gitkeep @@ -0,0 +1 @@ + diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php deleted file mode 100644 index a9898e3..0000000 --- a/resources/views/welcome.blade.php +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - Laravel - - - - - - - - - - - - diff --git a/routes/api.php b/routes/api.php index 43daedb..2be2a50 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,16 +2,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; -use App\Http\Controllers\CustomerController; -use App\Http\Controllers\AuthController; -use Illuminate\Container\Attributes\Auth; -Route::get('/user', function (Request $request) { +Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { return $request->user(); -})->middleware('auth:sanctum'); - -Route::apiResource('customers', CustomerController::class)->middleware('auth:sanctum'); - -Route::post('/register', [AuthController::class, 'register']); -Route::post('/login', [AuthController::class, 'login']); -Route::post('/logout', [AuthController::class, 'logout'])->middleware('auth:sanctum'); +}); diff --git a/routes/auth.php b/routes/auth.php new file mode 100644 index 0000000..9cf5ffd --- /dev/null +++ b/routes/auth.php @@ -0,0 +1,37 @@ +middleware('guest') + ->name('register'); + +Route::post('/login', [AuthenticatedSessionController::class, 'store']) + ->middleware('guest') + ->name('login'); + +Route::post('/forgot-password', [PasswordResetLinkController::class, 'store']) + ->middleware('guest') + ->name('password.email'); + +Route::post('/reset-password', [NewPasswordController::class, 'store']) + ->middleware('guest') + ->name('password.store'); + +Route::get('/verify-email/{id}/{hash}', VerifyEmailController::class) + ->middleware(['auth', 'signed', 'throttle:6,1']) + ->name('verification.verify'); + +Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store']) + ->middleware(['auth', 'throttle:6,1']) + ->name('verification.send'); + +Route::post('/logout', [AuthenticatedSessionController::class, 'destroy']) + ->middleware('auth') + ->name('logout'); diff --git a/routes/web.php b/routes/web.php index 7c4d255..cdd4027 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,3 +1,9 @@ app()->version()]; +}); + +require __DIR__.'/auth.php'; diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..ce0c57f --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,20 @@ +import defaultTheme from 'tailwindcss/defaultTheme'; + +/** @type {import('tailwindcss').Config} */ +export default { + content: [ + './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php', + './storage/framework/views/*.php', + './resources/**/*.blade.php', + './resources/**/*.js', + './resources/**/*.vue', + ], + theme: { + extend: { + fontFamily: { + sans: ['Figtree', ...defaultTheme.fontFamily.sans], + }, + }, + }, + plugins: [], +}; diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php new file mode 100644 index 0000000..2236551 --- /dev/null +++ b/tests/Feature/Auth/AuthenticationTest.php @@ -0,0 +1,47 @@ +create(); + + $response = $this->post('/login', [ + 'email' => $user->email, + 'password' => 'password', + ]); + + $this->assertAuthenticated(); + $response->assertNoContent(); + } + + public function test_users_can_not_authenticate_with_invalid_password(): void + { + $user = User::factory()->create(); + + $this->post('/login', [ + 'email' => $user->email, + 'password' => 'wrong-password', + ]); + + $this->assertGuest(); + } + + public function test_users_can_logout(): void + { + $user = User::factory()->create(); + + $response = $this->actingAs($user)->post('/logout'); + + $this->assertGuest(); + $response->assertNoContent(); + } +} diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php new file mode 100644 index 0000000..2db7299 --- /dev/null +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -0,0 +1,49 @@ +unverified()->create(); + + Event::fake(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1($user->email)] + ); + + $response = $this->actingAs($user)->get($verificationUrl); + + Event::assertDispatched(Verified::class); + $this->assertTrue($user->fresh()->hasVerifiedEmail()); + $response->assertRedirect(config('app.frontend_url').'/dashboard?verified=1'); + } + + public function test_email_is_not_verified_with_invalid_hash(): void + { + $user = User::factory()->unverified()->create(); + + $verificationUrl = URL::temporarySignedRoute( + 'verification.verify', + now()->addMinutes(60), + ['id' => $user->id, 'hash' => sha1('wrong-email')] + ); + + $this->actingAs($user)->get($verificationUrl); + + $this->assertFalse($user->fresh()->hasVerifiedEmail()); + } +} diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php new file mode 100644 index 0000000..9b652bc --- /dev/null +++ b/tests/Feature/Auth/PasswordResetTest.php @@ -0,0 +1,49 @@ +create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class); + } + + public function test_password_can_be_reset_with_valid_token(): void + { + Notification::fake(); + + $user = User::factory()->create(); + + $this->post('/forgot-password', ['email' => $user->email]); + + Notification::assertSentTo($user, ResetPassword::class, function (object $notification) use ($user) { + $response = $this->post('/reset-password', [ + 'token' => $notification->token, + 'email' => $user->email, + 'password' => 'password', + 'password_confirmation' => 'password', + ]); + + $response + ->assertSessionHasNoErrors() + ->assertStatus(200); + + return true; + }); + } +} diff --git a/tests/Feature/Auth/RegistrationTest.php b/tests/Feature/Auth/RegistrationTest.php new file mode 100644 index 0000000..b48e150 --- /dev/null +++ b/tests/Feature/Auth/RegistrationTest.php @@ -0,0 +1,24 @@ +post('/register', [ + 'name' => 'Test User', + 'email' => 'test@example.com', + 'password' => 'password', + 'password_confirmation' => 'password', + ]); + + $this->assertAuthenticated(); + $response->assertNoContent(); + } +} diff --git a/vite.config.js b/vite.config.js deleted file mode 100644 index 498ee23..0000000 --- a/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from "vite"; -import laravel from "laravel-vite-plugin"; - -export default defineConfig({ - plugins: [ - laravel({ - input: ["resources/css/app.css", "resources/js/app.js"], - refresh: true, - }), - ], -}); From 8125e78de2082a0ad029ff82c4bbe4a9ec59e7c4 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 31 Oct 2024 15:04:21 +0700 Subject: [PATCH 004/184] matikan pengecualian --- bootstrap/app.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bootstrap/app.php b/bootstrap/app.php index e7e7bdb..641f9df 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -6,9 +6,9 @@ return Application::configure(basePath: dirname(__DIR__)) ->withRouting( - web: __DIR__.'/../routes/web.php', - api: __DIR__.'/../routes/api.php', - commands: __DIR__.'/../routes/console.php', + web: __DIR__ . '/../routes/web.php', + api: __DIR__ . '/../routes/api.php', + commands: __DIR__ . '/../routes/console.php', health: '/up', ) ->withMiddleware(function (Middleware $middleware) { @@ -20,7 +20,9 @@ 'verified' => \App\Http\Middleware\EnsureEmailIsVerified::class, ]); - // + // $middleware->validateCsrfTokens(except: [ + // '*', + // ]); }) ->withExceptions(function (Exceptions $exceptions) { // From 8c5265fb410857712de440dd163ee39c13120733 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 1 Nov 2024 14:47:15 +0700 Subject: [PATCH 005/184] pembuatan tabel customer --- app/Http/Controllers/CustomerController.php | 51 ++++++++++++++ app/Models/Customer.php | 22 +++++++ app/Policies/CustomerPolicy.php | 66 +++++++++++++++++++ database/factories/CustomerFactory.php | 23 +++++++ ...24_11_01_021016_create_customers_table.php | 38 +++++++++++ database/seeders/CustomerSeeder.php | 31 +++++++++ routes/api.php | 5 ++ 7 files changed, 236 insertions(+) create mode 100644 app/Http/Controllers/CustomerController.php create mode 100644 app/Models/Customer.php create mode 100644 app/Policies/CustomerPolicy.php create mode 100644 database/factories/CustomerFactory.php create mode 100644 database/migrations/2024_11_01_021016_create_customers_table.php create mode 100644 database/seeders/CustomerSeeder.php diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php new file mode 100644 index 0000000..86e593e --- /dev/null +++ b/app/Http/Controllers/CustomerController.php @@ -0,0 +1,51 @@ +json($customers); + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + // + } + + /** + * Display the specified resource. + */ + public function show(Customer $customer) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Customer $customer) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Customer $customer) + { + // + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php new file mode 100644 index 0000000..bc3f261 --- /dev/null +++ b/app/Models/Customer.php @@ -0,0 +1,22 @@ + + */ +class CustomerFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/migrations/2024_11_01_021016_create_customers_table.php b/database/migrations/2024_11_01_021016_create_customers_table.php new file mode 100644 index 0000000..25809c2 --- /dev/null +++ b/database/migrations/2024_11_01_021016_create_customers_table.php @@ -0,0 +1,38 @@ +id(); + $table->string('name', 100); + $table->string('phone', 15); + $table->string('alamat', 255)->nullable(); + $table->string('kategori', 100)->nullable(); + $table->string('pekerjaan', 200)->nullable(); + $table->string('sertifikat', 50)->nullable(); + $table->decimal('nilai_transaksi')->nullable(); + $table->decimal('harga_real')->nullable(); + $table->decimal('harga_kesepakatan')->nullable(); + $table->decimal('data_pajak_pembeli')->nullable(); + $table->decimal('data_pajak_penjual')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('customers'); + } +}; diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php new file mode 100644 index 0000000..818a3c0 --- /dev/null +++ b/database/seeders/CustomerSeeder.php @@ -0,0 +1,31 @@ + $faker->name, + 'phone' => $faker->phoneNumber, + 'alamat' => $faker->address, + 'kategori' => $faker->word, + 'pekerjaan' => $faker->jobTitle, + 'sertifikat' => $faker->word, + 'nilai_transaksi' => $faker->randomFloat(2, 1000, 10000), + 'harga_real' => $faker->randomFloat(2, 500, 5000), + 'harga_kesepakatan' => $faker->randomFloat(2, 500, 5000), + 'data_pajak_pembeli' => $faker->randomFloat(2, 0, 1000), + 'data_pajak_penjual' => $faker->randomFloat(2, 0, 1000), + ]); + } + } +} diff --git a/routes/api.php b/routes/api.php index 2be2a50..421b134 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,7 +2,12 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\CustomerController; Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { return $request->user(); }); + +Route::middleware(['auth:sanctum'])->group(function () { + Route::apiResource('customers', CustomerController::class); +}); From edbb2b5db2a99f887dc0ef330cfb88a0a0cbfad8 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 2 Nov 2024 15:24:55 +0700 Subject: [PATCH 006/184] melengkapi controller customer --- app/Http/Controllers/CustomerController.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 86e593e..b086280 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -30,7 +30,8 @@ public function store(Request $request) */ public function show(Customer $customer) { - // + $customer = Customer::find($customer->id); + return response()->json($customer); } /** @@ -38,7 +39,9 @@ public function show(Customer $customer) */ public function update(Request $request, Customer $customer) { - // + $customer = Customer::find($customer->id); + $customer->update($request->all()); + return response()->json($customer); } /** @@ -46,6 +49,8 @@ public function update(Request $request, Customer $customer) */ public function destroy(Customer $customer) { - // + $customer = Customer::find($customer->id); + $customer->delete(); + return response()->json($customer); } } From dacd18acfcc01667e9696728ee07fb6aa6907282 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 2 Nov 2024 23:04:47 +0700 Subject: [PATCH 007/184] tambah seeder --- .env.example | 6 ++++-- database/seeders/CustomerSeeder.php | 2 +- database/seeders/DatabaseSeeder.php | 9 ++++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.env.example b/.env.example index a1b3de4..6ec0921 100644 --- a/.env.example +++ b/.env.example @@ -3,7 +3,10 @@ APP_ENV=local APP_KEY= APP_DEBUG=true APP_TIMEZONE=UTC -APP_URL=http://localhost +APP_URL=http://localhost:8000 +FRONTEND_URL=http://localhost:3000 +SANCTUM_STATEFUL_DOMAINS=localhost +SESSION_DOMAIN=null APP_LOCALE=en APP_FALLBACK_LOCALE=en @@ -32,7 +35,6 @@ SESSION_DRIVER=database SESSION_LIFETIME=120 SESSION_ENCRYPT=false SESSION_PATH=/ -SESSION_DOMAIN=null BROADCAST_CONNECTION=log FILESYSTEM_DISK=local diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php index 818a3c0..fc83bf3 100644 --- a/database/seeders/CustomerSeeder.php +++ b/database/seeders/CustomerSeeder.php @@ -12,7 +12,7 @@ public function run() { $faker = Faker::create(); - foreach (range(1, 20) as $index) { + foreach (range(1, 100) as $index) { Customer::create([ 'name' => $faker->name, 'phone' => $faker->phoneNumber, diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d01a0ef..e269e4e 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -3,8 +3,8 @@ namespace Database\Seeders; use App\Models\User; -// use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use Illuminate\Support\Facades\Hash; class DatabaseSeeder extends Seeder { @@ -13,11 +13,14 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // User::factory(10)->create(); + // Create 10 random users + User::factory(10)->create(); + // Create a specific user User::factory()->create([ 'name' => 'Test User', - 'email' => 'test@example.com', + 'email' => 'test@larapi.test', + 'password' => Hash::make('password'), ]); } } From 97b4347dd5094b11f3b4ff490ce63f644147a95c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 4 Nov 2024 07:39:24 +0700 Subject: [PATCH 008/184] update .env.example --- .env.example | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.env.example b/.env.example index 6ec0921..f973493 100644 --- a/.env.example +++ b/.env.example @@ -1,12 +1,11 @@ APP_NAME=Laravel APP_ENV=local -APP_KEY= +APP_KEY=base64:tMiKdI/3GuqLAKyBIe+Mv8cdrM04xfP/Onbvbtofc7A= APP_DEBUG=true APP_TIMEZONE=UTC -APP_URL=http://localhost:8000 +APP_URL=http://larapi.test FRONTEND_URL=http://localhost:3000 -SANCTUM_STATEFUL_DOMAINS=localhost -SESSION_DOMAIN=null +SANCTUM_STATEFUL_DOMAIN=localhost:3000 APP_LOCALE=en APP_FALLBACK_LOCALE=en @@ -35,6 +34,7 @@ SESSION_DRIVER=database SESSION_LIFETIME=120 SESSION_ENCRYPT=false SESSION_PATH=/ +SESSION_DOMAIN=null BROADCAST_CONNECTION=log FILESYSTEM_DISK=local From 5006e94eaa222d2029ca4d3edd92242c330b7a37 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 4 Nov 2024 11:36:37 +0700 Subject: [PATCH 009/184] update seeder --- .env.example | 2 +- composer.lock | 1085 +++++++++++++++-- .../0001_01_01_000000_create_users_table.php | 1 + database/seeders/DatabaseSeeder.php | 3 + 4 files changed, 1017 insertions(+), 74 deletions(-) diff --git a/.env.example b/.env.example index f973493..98dc89d 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ APP_NAME=Laravel APP_ENV=local -APP_KEY=base64:tMiKdI/3GuqLAKyBIe+Mv8cdrM04xfP/Onbvbtofc7A= +APP_KEY= APP_DEBUG=true APP_TIMEZONE=UTC APP_URL=http://larapi.test diff --git a/composer.lock b/composer.lock index b755063..0a39f96 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "785aaa5464fc438ca2615f92095171f0", + "content-hash": "f72e284aec6964ba6a65b4571522b0b7", "packages": [ { "name": "brick/math", @@ -1992,20 +1992,20 @@ }, { "name": "nesbot/carbon", - "version": "3.8.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "bbd3eef89af8ba66a3aa7952b5439168fbcc529f" + "reference": "10ac0aa86b8062219ce21e8189123d611ca3ecd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/bbd3eef89af8ba66a3aa7952b5439168fbcc529f", - "reference": "bbd3eef89af8ba66a3aa7952b5439168fbcc529f", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/10ac0aa86b8062219ce21e8189123d611ca3ecd9", + "reference": "10ac0aa86b8062219ce21e8189123d611ca3ecd9", "shasum": "" }, "require": { - "carbonphp/carbon-doctrine-types": "*", + "carbonphp/carbon-doctrine-types": "<100.0", "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", @@ -2094,7 +2094,7 @@ "type": "tidelift" } ], - "time": "2024-08-19T06:22:39+00:00" + "time": "2024-11-03T16:02:24+00:00" }, { "name": "nette/schema", @@ -5677,6 +5677,146 @@ } ], "packages-dev": [ + { + "name": "brianium/paratest", + "version": "v7.6.0", + "source": { + "type": "git", + "url": "https://github.com/paratestphp/paratest.git", + "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paratestphp/paratest/zipball/68ff89a8de47d086588e391a516d2a5b5fde6254", + "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-pcre": "*", + "ext-reflection": "*", + "ext-simplexml": "*", + "fidry/cpu-core-counter": "^1.2.0", + "jean85/pretty-package-versions": "^2.0.6", + "php": "~8.2.0 || ~8.3.0 || ~8.4.0", + "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-file-iterator": "^5.1.0", + "phpunit/php-timer": "^7.0.1", + "phpunit/phpunit": "^11.4.1", + "sebastian/environment": "^7.2.0", + "symfony/console": "^6.4.11 || ^7.1.5", + "symfony/process": "^6.4.8 || ^7.1.5" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0.0", + "ext-pcov": "*", + "ext-posix": "*", + "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan-deprecation-rules": "^1.2.1", + "phpstan/phpstan-phpunit": "^1.4.0", + "phpstan/phpstan-strict-rules": "^1.6.1", + "squizlabs/php_codesniffer": "^3.10.3", + "symfony/filesystem": "^6.4.9 || ^7.1.5" + }, + "bin": [ + "bin/paratest", + "bin/paratest_for_phpstorm" + ], + "type": "library", + "autoload": { + "psr-4": { + "ParaTest\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Scaturro", + "email": "scaturrob@gmail.com", + "role": "Developer" + }, + { + "name": "Filippo Tessarotto", + "email": "zoeslam@gmail.com", + "role": "Developer" + } + ], + "description": "Parallel testing for PHP", + "homepage": "https://github.com/paratestphp/paratest", + "keywords": [ + "concurrent", + "parallel", + "phpunit", + "testing" + ], + "support": { + "issues": "https://github.com/paratestphp/paratest/issues", + "source": "https://github.com/paratestphp/paratest/tree/v7.6.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/Slamdunk", + "type": "github" + }, + { + "url": "https://paypal.me/filippotessarotto", + "type": "paypal" + } + ], + "time": "2024-10-15T12:38:31+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "1.1.3", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/1.1.3" + }, + "time": "2024-01-30T19:34:25+00:00" + }, { "name": "fakerphp/faker", "version": "v1.23.1", @@ -5740,6 +5880,67 @@ }, "time": "2024-01-02T13:46:09+00:00" }, + { + "name": "fidry/cpu-core-counter", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/theofidry/cpu-core-counter.git", + "reference": "8520451a140d3f46ac33042715115e290cf5785f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", + "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "fidry/makefile": "^0.2.0", + "fidry/php-cs-fixer-config": "^1.1.2", + "phpstan/extension-installer": "^1.2.0", + "phpstan/phpstan": "^1.9.2", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-phpunit": "^1.2.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^8.5.31 || ^9.5.26", + "webmozarts/strict-phpunit": "^7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Fidry\\CpuCoreCounter\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Théo FIDRY", + "email": "theo.fidry@gmail.com" + } + ], + "description": "Tiny utility to get the number of CPU cores.", + "keywords": [ + "CPU", + "core" + ], + "support": { + "issues": "https://github.com/theofidry/cpu-core-counter/issues", + "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" + }, + "funding": [ + { + "url": "https://github.com/theofidry", + "type": "github" + } + ], + "time": "2024-08-06T10:04:20+00:00" + }, { "name": "filp/whoops", "version": "2.16.0", @@ -5862,6 +6063,65 @@ }, "time": "2020-07-09T08:09:16+00:00" }, + { + "name": "jean85/pretty-package-versions", + "version": "2.0.6", + "source": { + "type": "git", + "url": "https://github.com/Jean85/pretty-package-versions.git", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", + "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", + "shasum": "" + }, + "require": { + "composer-runtime-api": "^2.0.0", + "php": "^7.1|^8.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^3.2", + "jean85/composer-provided-replaced-stub-package": "^1.0", + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^7.5|^8.5|^9.4", + "vimeo/psalm": "^4.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Jean85\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alessandro Lai", + "email": "alessandro.lai85@gmail.com" + } + ], + "description": "A library to get pretty versions strings of installed dependencies", + "keywords": [ + "composer", + "package", + "release", + "versions" + ], + "support": { + "issues": "https://github.com/Jean85/pretty-package-versions/issues", + "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" + }, + "time": "2024-03-08T09:58:59+00:00" + }, { "name": "laravel/breeze", "version": "v2.2.4", @@ -6260,69 +6520,469 @@ "object graph" ], "support": { - "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2024-06-12T14:39:25+00:00" + }, + { + "name": "nunomaduro/collision", + "version": "v8.5.0", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/collision.git", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", + "reference": "f5c101b929c958e849a633283adff296ed5f38f5", + "shasum": "" + }, + "require": { + "filp/whoops": "^2.16.0", + "nunomaduro/termwind": "^2.1.0", + "php": "^8.2.0", + "symfony/console": "^7.1.5" + }, + "conflict": { + "laravel/framework": "<11.0.0 || >=12.0.0", + "phpunit/phpunit": "<10.5.1 || >=12.0.0" + }, + "require-dev": { + "larastan/larastan": "^2.9.8", + "laravel/framework": "^11.28.0", + "laravel/pint": "^1.18.1", + "laravel/sail": "^1.36.0", + "laravel/sanctum": "^4.0.3", + "laravel/tinker": "^2.10.0", + "orchestra/testbench-core": "^9.5.3", + "pestphp/pest": "^2.36.0 || ^3.4.0", + "sebastian/environment": "^6.1.0 || ^7.2.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, + "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], + "psr-4": { + "NunoMaduro\\Collision\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Cli error handling for console/command-line PHP applications.", + "keywords": [ + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", + "php", + "symfony" + ], + "support": { + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2024-10-15T16:06:32+00:00" + }, + { + "name": "pestphp/pest", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest.git", + "reference": "179d46ce97d52bcb3f791449ae94025c3f32e3e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest/zipball/179d46ce97d52bcb3f791449ae94025c3f32e3e3", + "reference": "179d46ce97d52bcb3f791449ae94025c3f32e3e3", + "shasum": "" + }, + "require": { + "brianium/paratest": "^7.6.0", + "nunomaduro/collision": "^8.5.0", + "nunomaduro/termwind": "^2.2.0", + "pestphp/pest-plugin": "^3.0.0", + "pestphp/pest-plugin-arch": "^3.0.0", + "pestphp/pest-plugin-mutate": "^3.0.5", + "php": "^8.2.0", + "phpunit/phpunit": "^11.4.3" + }, + "conflict": { + "filp/whoops": "<2.16.0", + "phpunit/phpunit": ">11.4.3", + "sebastian/exporter": "<6.0.0", + "webmozart/assert": "<1.11.0" + }, + "require-dev": { + "pestphp/pest-dev-tools": "^3.3.0", + "pestphp/pest-plugin-type-coverage": "^3.1.0", + "symfony/process": "^7.1.6" + }, + "bin": [ + "bin/pest" + ], + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Mutate\\Plugins\\Mutate", + "Pest\\Plugins\\Configuration", + "Pest\\Plugins\\Bail", + "Pest\\Plugins\\Cache", + "Pest\\Plugins\\Coverage", + "Pest\\Plugins\\Init", + "Pest\\Plugins\\Environment", + "Pest\\Plugins\\Help", + "Pest\\Plugins\\Memory", + "Pest\\Plugins\\Only", + "Pest\\Plugins\\Printer", + "Pest\\Plugins\\ProcessIsolation", + "Pest\\Plugins\\Profile", + "Pest\\Plugins\\Retry", + "Pest\\Plugins\\Snapshot", + "Pest\\Plugins\\Verbose", + "Pest\\Plugins\\Version", + "Pest\\Plugins\\Parallel" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "files": [ + "src/Functions.php", + "src/Pest.php" + ], + "psr-4": { + "Pest\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "The elegant PHP Testing Framework.", + "keywords": [ + "framework", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "issues": "https://github.com/pestphp/pest/issues", + "source": "https://github.com/pestphp/pest/tree/v3.5.1" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-10-31T16:12:45+00:00" + }, + { + "name": "pestphp/pest-plugin", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin.git", + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e79b26c65bc11c41093b10150c1341cc5cdbea83", + "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0.0", + "composer-runtime-api": "^2.2.2", + "php": "^8.2" + }, + "conflict": { + "pestphp/pest": "<3.0.0" + }, + "require-dev": { + "composer/composer": "^2.7.9", + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Pest\\Plugin\\Manager" + }, + "autoload": { + "psr-4": { + "Pest\\Plugin\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest plugin manager", + "keywords": [ + "framework", + "manager", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin/tree/v3.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2024-09-08T23:21:41+00:00" + }, + { + "name": "pestphp/pest-plugin-arch", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-arch.git", + "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/0a27e55a270cfe73d8cb70551b91002ee2cb64b0", + "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0", + "shasum": "" + }, + "require": { + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "ta-tikoma/phpunit-architecture-test": "^0.8.4" + }, + "require-dev": { + "pestphp/pest": "^3.0.0", + "pestphp/pest-dev-tools": "^3.0.0" + }, + "type": "library", + "extra": { + "pest": { + "plugins": [ + "Pest\\Arch\\Plugin" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Pest\\Arch\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Arch plugin for Pest PHP.", + "keywords": [ + "arch", + "architecture", + "framework", + "pest", + "php", + "plugin", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.0.0" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + } + ], + "time": "2024-09-08T23:23:55+00:00" + }, + { + "name": "pestphp/pest-plugin-laravel", + "version": "v3.0.0", + "source": { + "type": "git", + "url": "https://github.com/pestphp/pest-plugin-laravel.git", + "reference": "7dd98c0c3b3542970ec21fce80ec5c88916ac469" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/7dd98c0c3b3542970ec21fce80ec5c88916ac469", + "reference": "7dd98c0c3b3542970ec21fce80ec5c88916ac469", + "shasum": "" + }, + "require": { + "laravel/framework": "^11.22.0", + "pestphp/pest": "^3.0.0", + "php": "^8.2.0" + }, + "require-dev": { + "laravel/dusk": "^8.2.5", + "orchestra/testbench": "^9.4.0", + "pestphp/pest-dev-tools": "^3.0.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Pest\\Laravel\\PestServiceProvider" + ] + }, + "pest": { + "plugins": [ + "Pest\\Laravel\\Plugin" + ] + } + }, + "autoload": { + "files": [ + "src/Autoload.php" + ], + "psr-4": { + "Pest\\Laravel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "The Pest Laravel Plugin", + "keywords": [ + "framework", + "laravel", + "pest", + "php", + "test", + "testing", + "unit" + ], + "support": { + "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v3.0.0" }, "funding": [ { - "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", - "type": "tidelift" + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-09-08T23:32:52+00:00" }, { - "name": "nunomaduro/collision", - "version": "v8.5.0", + "name": "pestphp/pest-plugin-mutate", + "version": "v3.0.5", "source": { "type": "git", - "url": "https://github.com/nunomaduro/collision.git", - "reference": "f5c101b929c958e849a633283adff296ed5f38f5" + "url": "https://github.com/pestphp/pest-plugin-mutate.git", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f5c101b929c958e849a633283adff296ed5f38f5", - "reference": "f5c101b929c958e849a633283adff296ed5f38f5", + "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/e10dbdc98c9e2f3890095b4fe2144f63a5717e08", + "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08", "shasum": "" }, "require": { - "filp/whoops": "^2.16.0", - "nunomaduro/termwind": "^2.1.0", - "php": "^8.2.0", - "symfony/console": "^7.1.5" - }, - "conflict": { - "laravel/framework": "<11.0.0 || >=12.0.0", - "phpunit/phpunit": "<10.5.1 || >=12.0.0" + "nikic/php-parser": "^5.2.0", + "pestphp/pest-plugin": "^3.0.0", + "php": "^8.2", + "psr/simple-cache": "^3.0.0" }, "require-dev": { - "larastan/larastan": "^2.9.8", - "laravel/framework": "^11.28.0", - "laravel/pint": "^1.18.1", - "laravel/sail": "^1.36.0", - "laravel/sanctum": "^4.0.3", - "laravel/tinker": "^2.10.0", - "orchestra/testbench-core": "^9.5.3", - "pestphp/pest": "^2.36.0 || ^3.4.0", - "sebastian/environment": "^6.1.0 || ^7.2.0" + "pestphp/pest": "^3.0.8", + "pestphp/pest-dev-tools": "^3.0.0", + "pestphp/pest-plugin-type-coverage": "^3.0.0" }, "type": "library", - "extra": { - "laravel": { - "providers": [ - "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" - ] - }, - "branch-alias": { - "dev-8.x": "8.x-dev" - } - }, "autoload": { - "files": [ - "./src/Adapters/Phpunit/Autoload.php" - ], "psr-4": { - "NunoMaduro\\Collision\\": "src/" + "Pest\\Mutate\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -6331,26 +6991,24 @@ ], "authors": [ { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" + "name": "Sandro Gehri", + "email": "sandrogehri@gmail.com" } ], - "description": "Cli error handling for console/command-line PHP applications.", + "description": "Mutates your code to find untested cases", "keywords": [ - "artisan", - "cli", - "command-line", - "console", - "error", - "handling", - "laravel", - "laravel-zero", + "framework", + "mutate", + "mutation", + "pest", "php", - "symfony" + "plugin", + "test", + "testing", + "unit" ], "support": { - "issues": "https://github.com/nunomaduro/collision/issues", - "source": "https://github.com/nunomaduro/collision" + "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v3.0.5" }, "funding": [ { @@ -6358,15 +7016,15 @@ "type": "custom" }, { - "url": "https://github.com/nunomaduro", + "url": "https://github.com/gehrisandro", "type": "github" }, { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" + "url": "https://github.com/nunomaduro", + "type": "github" } ], - "time": "2024-10-15T16:06:32+00:00" + "time": "2024-09-22T07:54:40+00:00" }, { "name": "phar-io/manifest", @@ -6486,6 +7144,228 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.4.1", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.1", + "ext-filter": "*", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.7", + "phpstan/phpdoc-parser": "^1.7", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.5", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-mockery": "^1.1", + "phpstan/phpstan-webmozart-assert": "^1.2", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" + }, + "time": "2024-05-21T05:55:05+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.9.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/1fb5ba8d045f5dd984ebded5b1cc66f29459422d", + "reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.3 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.18" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.9.0" + }, + "time": "2024-11-03T20:11:34+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.33.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + }, + "time": "2024-10-13T11:25:22+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "11.0.7", @@ -7081,16 +7961,16 @@ }, { "name": "sebastian/comparator", - "version": "6.2.0", + "version": "6.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "df95a6e827808debe3dbe190022dd0f643d5d909" + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/df95a6e827808debe3dbe190022dd0f643d5d909", - "reference": "df95a6e827808debe3dbe190022dd0f643d5d909", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/43d129d6a0f81c78bee378b46688293eb7ea3739", + "reference": "43d129d6a0f81c78bee378b46688293eb7ea3739", "shasum": "" }, "require": { @@ -7146,7 +8026,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", "security": "https://github.com/sebastianbergmann/comparator/security/policy", - "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.0" + "source": "https://github.com/sebastianbergmann/comparator/tree/6.2.1" }, "funding": [ { @@ -7154,7 +8034,7 @@ "type": "github" } ], - "time": "2024-10-30T13:12:44+00:00" + "time": "2024-10-31T05:30:08+00:00" }, { "name": "sebastian/complexity", @@ -7903,6 +8783,65 @@ ], "time": "2024-09-25T14:20:29+00:00" }, + { + "name": "ta-tikoma/phpunit-architecture-test", + "version": "0.8.4", + "source": { + "type": "git", + "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", + "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.18.0 || ^5.0.0", + "php": "^8.1.0", + "phpdocumentor/reflection-docblock": "^5.3.0", + "phpunit/phpunit": "^10.5.5 || ^11.0.0", + "symfony/finder": "^6.4.0 || ^7.0.0" + }, + "require-dev": { + "laravel/pint": "^1.13.7", + "phpstan/phpstan": "^1.10.52" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPUnit\\Architecture\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ni Shi", + "email": "futik0ma011@gmail.com" + }, + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Methods for testing application architecture", + "keywords": [ + "architecture", + "phpunit", + "stucture", + "test", + "testing" + ], + "support": { + "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", + "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.4" + }, + "time": "2024-01-05T14:10:56+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.3", diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 05fb5d9..97f1d63 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -16,6 +16,7 @@ public function up(): void $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); + $table->boolean('is_admin')->default(false); $table->string('password'); $table->rememberToken(); $table->timestamps(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index e269e4e..407b33a 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -22,5 +22,8 @@ public function run(): void 'email' => 'test@larapi.test', 'password' => Hash::make('password'), ]); + + // Create 100 random customers + $this->call(CustomerSeeder::class); } } From 282dc8854fcdab270612c522957bde4395ea26a2 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 4 Nov 2024 15:36:20 +0700 Subject: [PATCH 010/184] tambah profile controller --- .../Controllers/Auth/ProfileController.php | 26 +++++++++++++ app/Http/Controllers/CustomerController.php | 3 +- .../Requests/Auth/ProfileUpdateRequest.php | 38 +++++++++++++++++++ .../0001_01_01_000000_create_users_table.php | 1 + routes/api.php | 5 +++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/Auth/ProfileController.php create mode 100644 app/Http/Requests/Auth/ProfileUpdateRequest.php diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php new file mode 100644 index 0000000..c482b02 --- /dev/null +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -0,0 +1,26 @@ +user(); + + $validated = $request->validated(); + + $user->update($validated); + $user = $user->refresh(); + + $message['user'] = $user; + $message['success'] = true; + + return response()->json($message, 200); + } +} diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index b086280..3d67010 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -22,7 +22,8 @@ public function index() */ public function store(Request $request) { - // + $customer = Customer::create($request->all()); + return response()->json($customer); } /** diff --git a/app/Http/Requests/Auth/ProfileUpdateRequest.php b/app/Http/Requests/Auth/ProfileUpdateRequest.php new file mode 100644 index 0000000..b5ef3dd --- /dev/null +++ b/app/Http/Requests/Auth/ProfileUpdateRequest.php @@ -0,0 +1,38 @@ +|string> + */ + public function rules(): array + { + return [ + 'name' => ['required', 'string', 'max:255'], + 'email' => [ + 'required', + 'email', + 'max:255', + 'unique:' . User::class . ',email,' . $this->user()->id + ], + 'password' => ['nullable', 'string', 'min:8', 'confirmed'], + 'avatar' => ['nullable', 'image', 'max:2048', 'mimes:jpeg,png,jpg'], + ]; + } +} diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 97f1d63..bec36d4 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -17,6 +17,7 @@ public function up(): void $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->boolean('is_admin')->default(false); + $table->string('avatar')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); diff --git a/routes/api.php b/routes/api.php index 421b134..a4b9ee1 100644 --- a/routes/api.php +++ b/routes/api.php @@ -3,11 +3,16 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; use App\Http\Controllers\CustomerController; +use App\Http\Controllers\Auth\ProfileController; Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { return $request->user(); }); Route::middleware(['auth:sanctum'])->group(function () { + Route::get('profile', function (Request $request) { + return $request->user(); + }); + Route::put('profile', [ProfileController::class, 'update']); Route::apiResource('customers', CustomerController::class); }); From b61cdf3c39069b3efaed2dcaa4b0433b22412f5c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 4 Nov 2024 21:11:51 +0700 Subject: [PATCH 011/184] perbaikan seeder --- app/Http/Controllers/Auth/ProfileController.php | 12 +++++++++++- app/Models/User.php | 6 ++++++ database/factories/CustomerFactory.php | 13 ++++++++++++- database/factories/UserFactory.php | 9 +++++++-- .../0001_01_01_000000_create_users_table.php | 3 +++ database/seeders/DatabaseSeeder.php | 6 +++++- routes/api.php | 1 + 7 files changed, 45 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index c482b02..633aea3 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -4,17 +4,27 @@ use App\Http\Requests\Auth\ProfileUpdateRequest; use App\Http\Controllers\Controller; +use App\Models\User; use Illuminate\Http\Request; use Pest\Plugins\Profile; class ProfileController extends Controller { + + public function index() + { + $user = User::all(); + return response()->json($user); + } public function update(ProfileUpdateRequest $request) { $user = $request->user(); $validated = $request->validated(); - + if ($request->hasFile('avatar')) { + $avatarPath = $request->file('avatar')->store('avatars', 'public'); + $validated['avatar'] = $avatarPath; + } $user->update($validated); $user = $user->refresh(); diff --git a/app/Models/User.php b/app/Models/User.php index 3dfbd80..e7133a5 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -16,11 +16,17 @@ class User extends Authenticatable * The attributes that are mass assignable. * * @var array + * $table->id(); */ protected $fillable = [ 'name', 'email', 'password', + 'avatar', + 'phone', + 'address', + 'position', + 'is_admin', ]; /** diff --git a/database/factories/CustomerFactory.php b/database/factories/CustomerFactory.php index b077ca2..de30009 100644 --- a/database/factories/CustomerFactory.php +++ b/database/factories/CustomerFactory.php @@ -17,7 +17,18 @@ class CustomerFactory extends Factory public function definition(): array { return [ - // + 'name' => fake()->name(), + 'email' => fake()->unique()->safeEmail(), + 'phone' => fake()->phoneNumber(), + 'alamat' => fake()->address(), + 'kategori' => fake()->randomElement(['Bank', 'Pribadi']), + 'pekerjaan' => fake()->jobTitle(), + 'sertifikat' => fake()->randomElement(['SHM', 'SHU', 'HIBAH']), + 'nilai_transaksi' => fake()->randomFloat(2, 1000000, 1000000000), + 'harga_real' => fake()->randomFloat(2, 1000000, 1000000000), + 'harga_kesepakatan' => fake()->randomFloat(2, 1000000, 1000000000), + 'data_pajak_pembeli' => fake()->randomFloat(2, 1000000, 1000000000), + 'data_pajak_penjual' => fake()->randomFloat(2, 1000000, 1000000000), ]; } } diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 584104c..ef6bb47 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -28,6 +28,11 @@ public function definition(): array 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => static::$password ??= Hash::make('password'), + 'is_admin' => false, + 'avatar' => null, + 'phone' => fake()->phoneNumber(), + 'address' => fake()->address(), + 'position' => fake()->randomElement(['Keuangan', 'Staff', 'Supervisor', 'Owner', 'Manager']), 'remember_token' => Str::random(10), ]; } @@ -37,8 +42,8 @@ public function definition(): array */ public function unverified(): static { - return $this->state(fn (array $attributes) => [ - 'email_verified_at' => null, + return $this->state(fn(array $attributes) => [ + 'email_verified_at' => now(), ]); } } diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index bec36d4..d0f722b 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -18,6 +18,9 @@ public function up(): void $table->timestamp('email_verified_at')->nullable(); $table->boolean('is_admin')->default(false); $table->string('avatar')->nullable(); + $table->string('phone')->nullable(); + $table->text('address')->nullable(); + $table->string('position')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 407b33a..d49d096 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -16,10 +16,14 @@ public function run(): void // Create 10 random users User::factory(10)->create(); - // Create a specific user User::factory()->create([ 'name' => 'Test User', 'email' => 'test@larapi.test', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Manager', 'password' => Hash::make('password'), ]); diff --git a/routes/api.php b/routes/api.php index a4b9ee1..2770faf 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,5 +14,6 @@ return $request->user(); }); Route::put('profile', [ProfileController::class, 'update']); + Route::get('users', [ProfileController::class, 'index']); Route::apiResource('customers', CustomerController::class); }); From 15225d9c56c53296b90c43d850af40a55cc7ea88 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 4 Nov 2024 22:08:04 +0700 Subject: [PATCH 012/184] perbaikan seeder --- .../Controllers/Auth/ProfileController.php | 6 ++++++ app/Models/Customer.php | 3 +++ database/seeders/CustomerSeeder.php | 19 +------------------ database/seeders/DatabaseSeeder.php | 3 --- routes/api.php | 3 ++- 5 files changed, 12 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index 633aea3..84a0d88 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -16,6 +16,12 @@ public function index() $user = User::all(); return response()->json($user); } + + public function show($id) + { + $user = User::find($id); + return response()->json($user); + } public function update(ProfileUpdateRequest $request) { $user = $request->user(); diff --git a/app/Models/Customer.php b/app/Models/Customer.php index bc3f261..429223c 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -2,10 +2,13 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Customer extends Model { + use HasFactory; + protected $fillable = [ 'name', 'phone', diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php index fc83bf3..923c88b 100644 --- a/database/seeders/CustomerSeeder.php +++ b/database/seeders/CustomerSeeder.php @@ -4,28 +4,11 @@ use Illuminate\Database\Seeder; use App\Models\Customer; -use Faker\Factory as Faker; class CustomerSeeder extends Seeder { public function run() { - $faker = Faker::create(); - - foreach (range(1, 100) as $index) { - Customer::create([ - 'name' => $faker->name, - 'phone' => $faker->phoneNumber, - 'alamat' => $faker->address, - 'kategori' => $faker->word, - 'pekerjaan' => $faker->jobTitle, - 'sertifikat' => $faker->word, - 'nilai_transaksi' => $faker->randomFloat(2, 1000, 10000), - 'harga_real' => $faker->randomFloat(2, 500, 5000), - 'harga_kesepakatan' => $faker->randomFloat(2, 500, 5000), - 'data_pajak_pembeli' => $faker->randomFloat(2, 0, 1000), - 'data_pajak_penjual' => $faker->randomFloat(2, 0, 1000), - ]); - } + Customer::factory(100)->create(); } } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d49d096..1e538e6 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -26,8 +26,5 @@ public function run(): void 'position' => 'Manager', 'password' => Hash::make('password'), ]); - - // Create 100 random customers - $this->call(CustomerSeeder::class); } } diff --git a/routes/api.php b/routes/api.php index 2770faf..0d3039a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,6 +14,7 @@ return $request->user(); }); Route::put('profile', [ProfileController::class, 'update']); - Route::get('users', [ProfileController::class, 'index']); + Route::get('karyawans', [ProfileController::class, 'index']); + Route::get('karyawans/{id}', [ProfileController::class, 'show']); Route::apiResource('customers', CustomerController::class); }); From 919770fb4a9dea16fe8e661b4f00b5bc58be066a Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 5 Nov 2024 13:58:27 +0700 Subject: [PATCH 013/184] hapus avatar saat update --- .../Controllers/Auth/ProfileController.php | 19 ++++++---- app/Http/Controllers/CustomerController.php | 17 ++++++++- app/Models/Customer.php | 5 +++ database/factories/CustomerFactory.php | 35 +++++++++++++++++-- ...24_11_01_021016_create_customers_table.php | 3 +- 5 files changed, 67 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index 84a0d88..9cc817e 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -4,9 +4,8 @@ use App\Http\Requests\Auth\ProfileUpdateRequest; use App\Http\Controllers\Controller; +use Illuminate\Support\Facades\Storage; use App\Models\User; -use Illuminate\Http\Request; -use Pest\Plugins\Profile; class ProfileController extends Controller { @@ -25,18 +24,24 @@ public function show($id) public function update(ProfileUpdateRequest $request) { $user = $request->user(); - $validated = $request->validated(); + if ($request->hasFile('avatar')) { + if ($user->avatar) { + Storage::disk('public')->delete($user->avatar); + } + $avatarPath = $request->file('avatar')->store('avatars', 'public'); $validated['avatar'] = $avatarPath; } + + // Update the user's profile $user->update($validated); $user = $user->refresh(); - $message['user'] = $user; - $message['success'] = true; - - return response()->json($message, 200); + return response()->json([ + 'user' => $user, + 'success' => true, + ], 200); } } diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 3d67010..74ce68d 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -22,7 +22,22 @@ public function index() */ public function store(Request $request) { - $customer = Customer::create($request->all()); + $validatedData = $request->validate([ + 'name' => 'required|string|max:255', + 'phone' => 'required|string|max:15', + 'alamat' => 'required|string', + 'bank' => 'max:255', + 'kategori' => 'required|string', + 'pekerjaan' => 'max:255', + 'sertifikat' => 'required|string', + 'nilai_transaksi' => 'required|numeric', + 'harga_real' => 'required|numeric', + 'harga_kesepakatan' => 'required|numeric', + 'data_pajak_pembeli' => 'required|numeric', + 'data_pajak_penjual' => 'required|numeric', + ]); + + $customer = Customer::create($validatedData); return response()->json($customer); } diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 429223c..47596f6 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -14,6 +14,7 @@ class Customer extends Model 'phone', 'alamat', 'kategori', + 'bank', 'pekerjaan', 'sertifikat', 'nilai_transaksi', @@ -22,4 +23,8 @@ class Customer extends Model 'data_pajak_pembeli', 'data_pajak_penjual', ]; + + protected $casts = [ + 'pekerjaan' => 'array', + ]; } diff --git a/database/factories/CustomerFactory.php b/database/factories/CustomerFactory.php index de30009..6b0a9db 100644 --- a/database/factories/CustomerFactory.php +++ b/database/factories/CustomerFactory.php @@ -16,13 +16,42 @@ class CustomerFactory extends Factory */ public function definition(): array { + $pekerjaan = [ + 'SKMHT', + 'APHT', + 'Fidusia', + 'Jual beli', + 'Hibah', + 'Turun waris', + 'Aphb', + 'Pendirian PT', + 'Pendirian CV', + 'Pendirian yayasan', + 'Pendirian PT perorangan', + 'Pendirian akta cabang', + 'Perubahan PT', + 'Perub CV', + 'Perub Yayasan', + 'Pecah sertifikat', + 'Pengeringan', + 'PBG', + 'Peningkatan Hak' + ]; return [ 'name' => fake()->name(), - 'email' => fake()->unique()->safeEmail(), 'phone' => fake()->phoneNumber(), 'alamat' => fake()->address(), - 'kategori' => fake()->randomElement(['Bank', 'Pribadi']), - 'pekerjaan' => fake()->jobTitle(), + 'kategori' => fake()->randomElement(['Bank', 'Perorangan']), + 'bank' => fake()->randomElement([ + 'BPR BBA', + 'BPR Pala Pusat', + 'BPR Pala Cabang', + 'BPR Danamas Prime', + 'BPR Arum Mandiri', + 'BPRS Madina Mandiri', + 'BMT Sejahtera Ummat', + ]), + 'pekerjaan' => fake()->randomElement($pekerjaan), 'sertifikat' => fake()->randomElement(['SHM', 'SHU', 'HIBAH']), 'nilai_transaksi' => fake()->randomFloat(2, 1000000, 1000000000), 'harga_real' => fake()->randomFloat(2, 1000000, 1000000000), diff --git a/database/migrations/2024_11_01_021016_create_customers_table.php b/database/migrations/2024_11_01_021016_create_customers_table.php index 25809c2..73a236c 100644 --- a/database/migrations/2024_11_01_021016_create_customers_table.php +++ b/database/migrations/2024_11_01_021016_create_customers_table.php @@ -17,7 +17,8 @@ public function up(): void $table->string('phone', 15); $table->string('alamat', 255)->nullable(); $table->string('kategori', 100)->nullable(); - $table->string('pekerjaan', 200)->nullable(); + $table->text('pekerjaan')->nullable(); + $table->string('bank', 100)->nullable(); $table->string('sertifikat', 50)->nullable(); $table->decimal('nilai_transaksi')->nullable(); $table->decimal('harga_real')->nullable(); From 439e151c9763bfb38b02da9946c98e29cfde5c81 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 6 Nov 2024 14:32:35 +0700 Subject: [PATCH 014/184] tambah tabel order --- app/Http/Controllers/CustomerController.php | 33 +++++----- app/Http/Controllers/OrderController.php | 23 +++++++ app/Models/Customer.php | 5 ++ app/Models/Order.php | 30 +++++++++ app/Policies/OrderPolicy.php | 66 +++++++++++++++++++ database/factories/OrderFactory.php | 37 +++++++++++ .../2024_11_06_033508_create_orders_table.php | 34 ++++++++++ database/seeders/DatabaseSeeder.php | 6 ++ database/seeders/OrderSeeder.php | 18 +++++ routes/api.php | 3 + 10 files changed, 240 insertions(+), 15 deletions(-) create mode 100644 app/Http/Controllers/OrderController.php create mode 100644 app/Models/Order.php create mode 100644 app/Policies/OrderPolicy.php create mode 100644 database/factories/OrderFactory.php create mode 100644 database/migrations/2024_11_06_033508_create_orders_table.php create mode 100644 database/seeders/OrderSeeder.php diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 74ce68d..39d39f4 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -11,6 +11,21 @@ class CustomerController extends Controller /** * Display a listing of the resource. */ + public $validate = [ + 'name' => 'required|string|max:255', + 'phone' => 'required|string|max:15', + 'alamat' => 'required|string', + 'bank' => 'max:255', + 'kategori' => 'required|string', + 'pekerjaan' => 'max:255', + 'sertifikat' => 'required|string', + 'nilai_transaksi' => 'required|numeric', + 'harga_real' => 'required|numeric', + 'harga_kesepakatan' => 'required|numeric', + 'data_pajak_pembeli' => 'required|numeric', + 'data_pajak_penjual' => 'required|numeric', + ]; + public function index() { $customers = Customer::all(); @@ -22,20 +37,7 @@ public function index() */ public function store(Request $request) { - $validatedData = $request->validate([ - 'name' => 'required|string|max:255', - 'phone' => 'required|string|max:15', - 'alamat' => 'required|string', - 'bank' => 'max:255', - 'kategori' => 'required|string', - 'pekerjaan' => 'max:255', - 'sertifikat' => 'required|string', - 'nilai_transaksi' => 'required|numeric', - 'harga_real' => 'required|numeric', - 'harga_kesepakatan' => 'required|numeric', - 'data_pajak_pembeli' => 'required|numeric', - 'data_pajak_penjual' => 'required|numeric', - ]); + $validatedData = $request->validate($this->validate); $customer = Customer::create($validatedData); return response()->json($customer); @@ -56,7 +58,8 @@ public function show(Customer $customer) public function update(Request $request, Customer $customer) { $customer = Customer::find($customer->id); - $customer->update($request->all()); + $validatedData = $request->validate($this->validate); + $customer->update($validatedData); return response()->json($customer); } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php new file mode 100644 index 0000000..2aace2e --- /dev/null +++ b/app/Http/Controllers/OrderController.php @@ -0,0 +1,23 @@ +load('customer'); + return response()->json($orders); + } + + public function show(Order $order) + { + $order = Order::find($order->id)->load('customer'); + return response()->json($order); + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 47596f6..134d044 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -27,4 +27,9 @@ class Customer extends Model protected $casts = [ 'pekerjaan' => 'array', ]; + + public function orders() + { + return $this->hasMany(Order::class); + } } diff --git a/app/Models/Order.php b/app/Models/Order.php new file mode 100644 index 0000000..2e7243b --- /dev/null +++ b/app/Models/Order.php @@ -0,0 +1,30 @@ + 'array', + ]; + + public function customer() + { + return $this->belongsTo(Customer::class); + } +} diff --git a/app/Policies/OrderPolicy.php b/app/Policies/OrderPolicy.php new file mode 100644 index 0000000..efd76ba --- /dev/null +++ b/app/Policies/OrderPolicy.php @@ -0,0 +1,66 @@ + + */ +class OrderFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + $layanan_notaris = [ + 'Pembuatan Akta Otentik', + 'Pembuatan Wasiat', + 'Pengesahan Dokumen', + 'Peralihan Hak Tanah', + 'Pembuatan Surat Kuasa', + 'Jasa Legalitas' + ]; + return [ + 'customer_id' => fake()->numberBetween(1, 10), + 'order_date' => now(), + 'service' => fake()->randomElement($layanan_notaris), + 'price' => fake()->numberBetween(100000, 10000000), + 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), + 'paid' => fake()->numberBetween(100000, 10000000), + 'document' => ['KTP', 'PBB', 'KK'] + ]; + } +} diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php new file mode 100644 index 0000000..16f7751 --- /dev/null +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('customer_id'); + $table->date('order_date'); + $table->string('service'); + $table->decimal('price')->nullable(); + $table->string('payment_method')->nullable(); + $table->decimal('paid')->nullable(); + $table->text('document')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('orders'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 1e538e6..9e468d1 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -2,9 +2,12 @@ namespace Database\Seeders; +use App\Models\Customer; use App\Models\User; +use App\Models\Order; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; +use Pest\ArchPresets\Custom; class DatabaseSeeder extends Seeder { @@ -26,5 +29,8 @@ public function run(): void 'position' => 'Manager', 'password' => Hash::make('password'), ]); + + Customer::factory(500)->create(); + Order::factory(50)->create(); } } diff --git a/database/seeders/OrderSeeder.php b/database/seeders/OrderSeeder.php new file mode 100644 index 0000000..eeeb352 --- /dev/null +++ b/database/seeders/OrderSeeder.php @@ -0,0 +1,18 @@ +create(); + } +} diff --git a/routes/api.php b/routes/api.php index 0d3039a..a66c2d0 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\OrderController; use App\Http\Controllers\CustomerController; use App\Http\Controllers\Auth\ProfileController; @@ -16,5 +17,7 @@ Route::put('profile', [ProfileController::class, 'update']); Route::get('karyawans', [ProfileController::class, 'index']); Route::get('karyawans/{id}', [ProfileController::class, 'show']); + + Route::apiResource('orders', OrderController::class); Route::apiResource('customers', CustomerController::class); }); From c4e4646bcdb8c1f39f4f8a37aad9aaa282a10151 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 6 Nov 2024 21:41:36 +0700 Subject: [PATCH 015/184] tambah customer pagination --- app/Http/Controllers/CustomerController.php | 2 +- app/Http/Controllers/OrderController.php | 16 ++++++++++++++++ database/seeders/DatabaseSeeder.php | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 39d39f4..10f7e5d 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -28,7 +28,7 @@ class CustomerController extends Controller public function index() { - $customers = Customer::all(); + $customers = Customer::paginate(25); return response()->json($customers); } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 2aace2e..f75591f 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -9,6 +9,14 @@ class OrderController extends Controller { + private $validate = [ + 'order_date' => 'required', + 'service' => 'required', + 'price' => 'required', + 'paid' => 'required', + 'payment_method' => 'required', + 'document' => 'required' + ]; public function index() { $orders = Order::all()->load('customer'); @@ -20,4 +28,12 @@ public function show(Order $order) $order = Order::find($order->id)->load('customer'); return response()->json($order); } + + public function update(Request $request, Order $order) + { + $order = Order::find($order->id); + $validatedData = $request->validate($this->validate); + $order->update($validatedData); + return response()->json($order); + } } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 9e468d1..dbd948d 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -30,7 +30,7 @@ public function run(): void 'password' => Hash::make('password'), ]); - Customer::factory(500)->create(); + Customer::factory(150)->create(); Order::factory(50)->create(); } } From b26f4a055eebc5200c42d9554fa4eadbc47fa49f Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 6 Nov 2024 22:12:47 +0700 Subject: [PATCH 016/184] tambah pagination order --- app/Http/Controllers/OrderController.php | 2 +- database/seeders/DatabaseSeeder.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index f75591f..74269c7 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -19,7 +19,7 @@ class OrderController extends Controller ]; public function index() { - $orders = Order::all()->load('customer'); + $orders = Order::with('customer')->paginate(25); return response()->json($orders); } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index dbd948d..8c60fd0 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -31,6 +31,6 @@ public function run(): void ]); Customer::factory(150)->create(); - Order::factory(50)->create(); + Order::factory(150)->create(); } } From b787602693036cbae40471fce70a3914cd2fffda Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 7 Nov 2024 15:05:48 +0700 Subject: [PATCH 017/184] penambahan controller karyawan --- .env.example | 10 ++--- .../Controllers/Auth/ProfileController.php | 2 +- app/Http/Controllers/CustomerController.php | 2 +- app/Http/Controllers/KaryawanController.php | 40 +++++++++++++++++++ app/Http/Controllers/OrderController.php | 14 +++++++ app/Policies/UserPolicy.php | 23 +++++++++++ app/Providers/AppServiceProvider.php | 14 ++++++- database/seeders/DatabaseSeeder.php | 19 ++++++--- routes/api.php | 10 +++-- 9 files changed, 116 insertions(+), 18 deletions(-) create mode 100644 app/Http/Controllers/KaryawanController.php create mode 100644 app/Policies/UserPolicy.php diff --git a/.env.example b/.env.example index 98dc89d..17c64f8 100644 --- a/.env.example +++ b/.env.example @@ -1,15 +1,15 @@ APP_NAME=Laravel APP_ENV=local -APP_KEY= +APP_KEY=base64:tMiKdI/3GuqLAKyBIe+Mv8cdrM04xfP/Onbvbtofc7A= APP_DEBUG=true -APP_TIMEZONE=UTC +APP_TIMEZONE=Asia/Jakarta APP_URL=http://larapi.test FRONTEND_URL=http://localhost:3000 SANCTUM_STATEFUL_DOMAIN=localhost:3000 -APP_LOCALE=en -APP_FALLBACK_LOCALE=en -APP_FAKER_LOCALE=en_US +APP_LOCALE=id +APP_FALLBACK_LOCALE=id +APP_FAKER_LOCALE=id_ID APP_MAINTENANCE_DRIVER=file # APP_MAINTENANCE_STORE=database diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index 9cc817e..9df7dac 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -12,7 +12,7 @@ class ProfileController extends Controller public function index() { - $user = User::all(); + $user = User::paginate(25); return response()->json($user); } diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 10f7e5d..a5a4cc9 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -13,7 +13,7 @@ class CustomerController extends Controller */ public $validate = [ 'name' => 'required|string|max:255', - 'phone' => 'required|string|max:15', + 'phone' => 'required|string|max:20', 'alamat' => 'required|string', 'bank' => 'max:255', 'kategori' => 'required|string', diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php new file mode 100644 index 0000000..63d790d --- /dev/null +++ b/app/Http/Controllers/KaryawanController.php @@ -0,0 +1,40 @@ +json($user); + } + + public function show($id) + { + $user = User::find($id); + return response()->json($user); + } + + public function update(Request $request, $id) + { + $user = User::findOrFail($id); + $this->authorize('update', $user); + + $validatedData = $request->validate([ + 'name' => ['required', 'string', 'max:255'], + 'phone' => ['required', 'string', 'max:20'], + 'address' => ['required', 'string', 'max:255'], + 'position' => ['required', 'string', 'max:100'], + ]); + + $user->update($validatedData); + return response()->json($user); + } +} diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 74269c7..7a47cb8 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -36,4 +36,18 @@ public function update(Request $request, Order $order) $order->update($validatedData); return response()->json($order); } + + public function store(Request $request) + { + $validatedData = $request->validate($this->validate); + $order = Order::create($validatedData); + return response()->json($order); + } + + public function destroy(Order $order) + { + $order = Order::find($order->id); + $order->delete(); + return response()->json($order); + } } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php new file mode 100644 index 0000000..6ea6d68 --- /dev/null +++ b/app/Policies/UserPolicy.php @@ -0,0 +1,23 @@ +id === $user->id || $authUser->is_admin === 1; + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 96ddc37..b32cc00 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -2,11 +2,19 @@ namespace App\Providers; +use App\Models\User; +use App\Policies\UserPolicy; use Illuminate\Auth\Notifications\ResetPassword; -use Illuminate\Support\ServiceProvider; +// use Illuminate\Support\ServiceProvider; +use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; + class AppServiceProvider extends ServiceProvider { + protected $policies = [ + User::class => UserPolicy::class, + ]; + /** * Register any application services. */ @@ -21,7 +29,9 @@ public function register(): void public function boot(): void { ResetPassword::createUrlUsing(function (object $notifiable, string $token) { - return config('app.frontend_url')."/password-reset/$token?email={$notifiable->getEmailForPasswordReset()}"; + return config('app.frontend_url') . "/password-reset/$token?email={$notifiable->getEmailForPasswordReset()}"; }); + + $this->registerPolicies(); } } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 8c60fd0..7d50737 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -17,11 +17,23 @@ class DatabaseSeeder extends Seeder public function run(): void { // Create 10 random users - User::factory(10)->create(); + User::factory(100)->create(); + Customer::factory(150)->create(); + Order::factory(150)->create(); User::factory()->create([ - 'name' => 'Test User', + 'name' => 'Test Admin', 'email' => 'test@larapi.test', + 'is_admin' => true, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Manager', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test Manager', + 'email' => 'manager@larapi.test', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', @@ -29,8 +41,5 @@ public function run(): void 'position' => 'Manager', 'password' => Hash::make('password'), ]); - - Customer::factory(150)->create(); - Order::factory(150)->create(); } } diff --git a/routes/api.php b/routes/api.php index a66c2d0..c6752f6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; +use App\Http\Controllers\KaryawanController; use App\Http\Controllers\OrderController; use App\Http\Controllers\CustomerController; use App\Http\Controllers\Auth\ProfileController; @@ -15,9 +16,10 @@ return $request->user(); }); Route::put('profile', [ProfileController::class, 'update']); - Route::get('karyawans', [ProfileController::class, 'index']); - Route::get('karyawans/{id}', [ProfileController::class, 'show']); - Route::apiResource('orders', OrderController::class); - Route::apiResource('customers', CustomerController::class); + Route::apiResources([ + 'karyawans' => KaryawanController::class, + 'orders' => OrderController::class, + 'customers' => CustomerController::class + ]); }); From fe6ca10266aec19896db8dec8295d55201a9db6e Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 7 Nov 2024 20:57:08 +0700 Subject: [PATCH 018/184] perbaikan controller karyawan --- app/Http/Controllers/CustomerController.php | 2 ++ app/Http/Controllers/KaryawanController.php | 8 ++++++++ app/Policies/UserPolicy.php | 7 +++++++ database/seeders/DatabaseSeeder.php | 9 ++++----- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index a5a4cc9..b932fae 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -69,6 +69,8 @@ public function update(Request $request, Customer $customer) public function destroy(Customer $customer) { $customer = Customer::find($customer->id); + // saat hapus customer harus hapus semua order nya + $customer->orders()->delete(); $customer->delete(); return response()->json($customer); } diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 63d790d..898073e 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -37,4 +37,12 @@ public function update(Request $request, $id) $user->update($validatedData); return response()->json($user); } + + public function destroy($id) + { + $user = User::findOrFail($id); + $this->authorize('delete', $user); + $user->delete(); + return response()->json($user); + } } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 6ea6d68..6156753 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -20,4 +20,11 @@ public function update(User $authUser, User $user) // atau jika pengguna tersebut adalah admin return $authUser->id === $user->id || $authUser->is_admin === 1; } + + public function delete(User $authUser, User $user) + { + // Memeriksa apakah pengguna yang sedang login adalah pengguna yang sama + // atau jika pengguna tersebut adalah admin + return $authUser->id === $user->id || $authUser->is_admin === 1; + } } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 7d50737..1335909 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -16,11 +16,6 @@ class DatabaseSeeder extends Seeder */ public function run(): void { - // Create 10 random users - User::factory(100)->create(); - Customer::factory(150)->create(); - Order::factory(150)->create(); - User::factory()->create([ 'name' => 'Test Admin', 'email' => 'test@larapi.test', @@ -41,5 +36,9 @@ public function run(): void 'position' => 'Manager', 'password' => Hash::make('password'), ]); + + User::factory(100)->create(); + Customer::factory(150)->create(); + Order::factory(150)->create(); } } From c089cdca58cc88e99250d36ab3ddf73915514117 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 8 Nov 2024 15:32:31 +0700 Subject: [PATCH 019/184] memisah validasi karyawan --- .../Controllers/Auth/ProfileController.php | 18 +++++-- app/Http/Controllers/Dashboard.php | 48 +++++++++++++++++++ app/Http/Controllers/KaryawanController.php | 42 +++++++++++++--- .../Requests/Auth/ProfileUpdateRequest.php | 12 ++++- app/Policies/UserPolicy.php | 3 +- 5 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 app/Http/Controllers/Dashboard.php diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index 9df7dac..b4ed271 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -26,16 +26,28 @@ public function update(ProfileUpdateRequest $request) $user = $request->user(); $validated = $request->validated(); + // Menangani avatar if ($request->hasFile('avatar')) { + $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); + + // Hapus avatar lama jika ada if ($user->avatar) { Storage::disk('public')->delete($user->avatar); } + } else { + // Jika tidak ada file avatar, gunakan avatar yang ada + $validated['avatar'] = $user->avatar; + } - $avatarPath = $request->file('avatar')->store('avatars', 'public'); - $validated['avatar'] = $avatarPath; + // Hanya update password jika diisi + if (isset($validated['password']) && !empty($validated['password'])) { + $validated['password'] = bcrypt($validated['password']); + } else { + // Hapus password dari array validasi agar tidak diupdate + unset($validated['password']); } - // Update the user's profile + // Update profil pengguna $user->update($validated); $user = $user->refresh(); diff --git a/app/Http/Controllers/Dashboard.php b/app/Http/Controllers/Dashboard.php new file mode 100644 index 0000000..fef0042 --- /dev/null +++ b/app/Http/Controllers/Dashboard.php @@ -0,0 +1,48 @@ +authorize('update', $user); - $validatedData = $request->validate([ - 'name' => ['required', 'string', 'max:255'], - 'phone' => ['required', 'string', 'max:20'], - 'address' => ['required', 'string', 'max:255'], - 'position' => ['required', 'string', 'max:100'], + // Validasi manual + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'email' => 'required|email|max:255|unique:users,email,' . $id, + 'phone' => 'required|string', + 'address' => 'required|string', + 'position' => 'nullable|string', + 'password' => 'nullable|string|min:8|confirmed', + 'avatar' => 'nullable|image|max:2048|mimes:jpeg,png,jpg', ]); - $user->update($validatedData); - return response()->json($user); + // Menangani avatar + if ($request->hasFile('avatar')) { + $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); + + // Hapus avatar lama jika ada + if ($user->avatar) { + Storage::disk('public')->delete($user->avatar); + } + } else { + // Jika tidak ada file avatar, gunakan avatar yang ada + $validated['avatar'] = $user->avatar; + } + + // Hanya update password jika diisi + if (isset($validated['password']) && !empty($validated['password'])) { + $validated['password'] = bcrypt($validated['password']); + } else { + unset($validated['password']); + } + + $user->update($validated); + return response()->json([ + 'user' => $user, + 'success' => true + ], 200); } public function destroy($id) diff --git a/app/Http/Requests/Auth/ProfileUpdateRequest.php b/app/Http/Requests/Auth/ProfileUpdateRequest.php index b5ef3dd..9ef8188 100644 --- a/app/Http/Requests/Auth/ProfileUpdateRequest.php +++ b/app/Http/Requests/Auth/ProfileUpdateRequest.php @@ -23,7 +23,7 @@ public function authorize(): bool */ public function rules(): array { - return [ + $rules = [ 'name' => ['required', 'string', 'max:255'], 'email' => [ 'required', @@ -32,7 +32,15 @@ public function rules(): array 'unique:' . User::class . ',email,' . $this->user()->id ], 'password' => ['nullable', 'string', 'min:8', 'confirmed'], - 'avatar' => ['nullable', 'image', 'max:2048', 'mimes:jpeg,png,jpg'], + 'avatar' => ['nullable'], ]; + + if (is_string($this->avatar)) { + unset($rules['avatar']); + } elseif ($this->hasFile('avatar')) { + $rules['avatar'] = ['image', 'max:2048', 'mimes:jpeg,png,jpg']; + } + + return $rules; } } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 6156753..bbd9b6e 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -25,6 +25,7 @@ public function delete(User $authUser, User $user) { // Memeriksa apakah pengguna yang sedang login adalah pengguna yang sama // atau jika pengguna tersebut adalah admin - return $authUser->id === $user->id || $authUser->is_admin === 1; + // dan jika user yang dihapus bukan admin + return ($authUser->id === $user->id || $authUser->is_admin === 1) && $user->is_admin !== 1; } } From 1f961753e939fd684d5089772dfe919742582609 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 8 Nov 2024 21:46:47 +0700 Subject: [PATCH 020/184] tambah beberapa kondisi --- .../Controllers/Auth/ProfileController.php | 5 +++++ app/Http/Controllers/KaryawanController.php | 20 ++++++++++++++++--- .../Requests/Auth/ProfileUpdateRequest.php | 3 +++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index b4ed271..494c70e 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -47,6 +47,11 @@ public function update(ProfileUpdateRequest $request) unset($validated['password']); } + //abaikan position jika diisi selain oleh is_admin + if (isset($validated['position']) && $user->is_admin !== 1) { + unset($validated['position']); + } + // Update profil pengguna $user->update($validated); $user = $user->refresh(); diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index c149d1c..37c9f23 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -26,6 +26,7 @@ public function show($id) public function update(Request $request, $id) { $user = User::findOrFail($id); + $requested_user = $request->user(); $this->authorize('update', $user); // Validasi manual @@ -36,11 +37,13 @@ public function update(Request $request, $id) 'address' => 'required|string', 'position' => 'nullable|string', 'password' => 'nullable|string|min:8|confirmed', - 'avatar' => 'nullable|image|max:2048|mimes:jpeg,png,jpg', + 'avatar' => 'nullable', ]); - // Menangani avatar - if ($request->hasFile('avatar')) { + // Abaikan 'avatar' jika merupakan string, hanya lanjutkan jika file + if (is_string($request->avatar)) { + unset($validated['avatar']); + } elseif ($request->hasFile('avatar')) { $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); // Hapus avatar lama jika ada @@ -59,9 +62,20 @@ public function update(Request $request, $id) unset($validated['password']); } + // Cek jika user bukan admin dan coba mengupdate position, maka abaikan perubahan position + if ($requested_user->is_admin !== 1 && isset($validated['position'])) { + $validated['position'] = $user->position; + $message = 'Data tersimpan, position tidak bisa diupdate'; + } else { + $message = 'Data tersimpan'; + } + + // Update user dengan data yang tervalidasi $user->update($validated); + return response()->json([ 'user' => $user, + 'message' => $message, 'success' => true ], 200); } diff --git a/app/Http/Requests/Auth/ProfileUpdateRequest.php b/app/Http/Requests/Auth/ProfileUpdateRequest.php index 9ef8188..fd7edb5 100644 --- a/app/Http/Requests/Auth/ProfileUpdateRequest.php +++ b/app/Http/Requests/Auth/ProfileUpdateRequest.php @@ -31,6 +31,9 @@ public function rules(): array 'max:255', 'unique:' . User::class . ',email,' . $this->user()->id ], + 'phone' => ['required', 'string'], + 'address' => ['required', 'string'], + 'position' => ['nullable', 'string'], 'password' => ['nullable', 'string', 'min:8', 'confirmed'], 'avatar' => ['nullable'], ]; From bd83d1de888e3efec8727f272a08e4d3833b5f2c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 20 Nov 2024 15:11:02 +0700 Subject: [PATCH 021/184] change app_url --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 17c64f8..8ccf90b 100644 --- a/.env.example +++ b/.env.example @@ -3,7 +3,7 @@ APP_ENV=local APP_KEY=base64:tMiKdI/3GuqLAKyBIe+Mv8cdrM04xfP/Onbvbtofc7A= APP_DEBUG=true APP_TIMEZONE=Asia/Jakarta -APP_URL=http://larapi.test +APP_URL=http://localhost:8000 FRONTEND_URL=http://localhost:3000 SANCTUM_STATEFUL_DOMAIN=localhost:3000 @@ -65,4 +65,4 @@ AWS_DEFAULT_REGION=us-east-1 AWS_BUCKET= AWS_USE_PATH_STYLE_ENDPOINT=false -VITE_APP_NAME="${APP_NAME}" +VITE_APP_NAME="${APP_NAME}" \ No newline at end of file From c1bd6032e70a7c03b434234df47787c6f3b72fe3 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 21 Nov 2024 14:34:30 +0700 Subject: [PATCH 022/184] tambah tabel jobdesk --- app/Models/Customer.php | 5 +++ app/Models/JobDesk.php | 36 ++++++++++++++++++ database/factories/JobDeskFactory.php | 23 +++++++++++ ...24_11_01_021016_create_customers_table.php | 12 +++--- .../2024_11_06_033508_create_orders_table.php | 4 +- ...024_11_21_140428_create_job_desk_table.php | 34 +++++++++++++++++ larapi | Bin 0 -> 200704 bytes 7 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 app/Models/JobDesk.php create mode 100644 database/factories/JobDeskFactory.php create mode 100644 database/migrations/2024_11_21_140428_create_job_desk_table.php create mode 100644 larapi diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 134d044..26f7519 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -32,4 +32,9 @@ public function orders() { return $this->hasMany(Order::class); } + + public function jobDesks() + { + return $this->hasMany(JobDesk::class); + } } diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php new file mode 100644 index 0000000..751755b --- /dev/null +++ b/app/Models/JobDesk.php @@ -0,0 +1,36 @@ +belongsTo(Customer::class); + } + + public function order() + { + return $this->belongsTo(Order::class); + } + + public function user() + { + return $this->belongsTo(User::class); + } +} diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php new file mode 100644 index 0000000..406bbc4 --- /dev/null +++ b/database/factories/JobDeskFactory.php @@ -0,0 +1,23 @@ + + */ +class JobDeskFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } +} diff --git a/database/migrations/2024_11_01_021016_create_customers_table.php b/database/migrations/2024_11_01_021016_create_customers_table.php index 73a236c..7495027 100644 --- a/database/migrations/2024_11_01_021016_create_customers_table.php +++ b/database/migrations/2024_11_01_021016_create_customers_table.php @@ -14,17 +14,17 @@ public function up(): void Schema::create('customers', function (Blueprint $table) { $table->id(); $table->string('name', 100); - $table->string('phone', 15); + $table->string('phone', 20); $table->string('alamat', 255)->nullable(); $table->string('kategori', 100)->nullable(); $table->text('pekerjaan')->nullable(); $table->string('bank', 100)->nullable(); $table->string('sertifikat', 50)->nullable(); - $table->decimal('nilai_transaksi')->nullable(); - $table->decimal('harga_real')->nullable(); - $table->decimal('harga_kesepakatan')->nullable(); - $table->decimal('data_pajak_pembeli')->nullable(); - $table->decimal('data_pajak_penjual')->nullable(); + $table->integer('nilai_transaksi')->nullable(); + $table->integer('harga_real')->nullable(); + $table->integer('harga_kesepakatan')->nullable(); + $table->integer('data_pajak_pembeli')->nullable(); + $table->integer('data_pajak_penjual')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php index 16f7751..f5e4ba8 100644 --- a/database/migrations/2024_11_06_033508_create_orders_table.php +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -16,9 +16,9 @@ public function up(): void $table->string('customer_id'); $table->date('order_date'); $table->string('service'); - $table->decimal('price')->nullable(); + $table->integer('price')->nullable(); $table->string('payment_method')->nullable(); - $table->decimal('paid')->nullable(); + $table->integer('paid')->nullable(); $table->text('document')->nullable(); $table->timestamps(); }); diff --git a/database/migrations/2024_11_21_140428_create_job_desk_table.php b/database/migrations/2024_11_21_140428_create_job_desk_table.php new file mode 100644 index 0000000..130ed2a --- /dev/null +++ b/database/migrations/2024_11_21_140428_create_job_desk_table.php @@ -0,0 +1,34 @@ +id(); + $table->string('customer_id'); + $table->string('order_id'); + $table->string('user_id'); + $table->string('jobdesk'); + $table->date('tanggal_pengerjaan')->nullable(); + $table->date('tanggal_selesai')->nullable(); + $table->string('status')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('job_desk'); + } +}; diff --git a/larapi b/larapi new file mode 100644 index 0000000000000000000000000000000000000000..3117c62f2ed380cbecd71e7c9d4de67b4444dfa6 GIT binary patch literal 200704 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 VB2DKQ{zqQ Date: Mon, 25 Nov 2024 15:25:32 +0700 Subject: [PATCH 023/184] ganti jobdesks table --- app/Http/Controllers/JobdeskController.php | 20 +++++++++++++++++++ app/Http/Controllers/OrderController.php | 3 +-- app/Models/Customer.php | 2 +- app/Models/JobDesk.php | 2 +- app/Models/Order.php | 5 +++++ database/factories/JobDeskFactory.php | 13 +++++++++--- ...24_11_23_124844_create_jobdesks_table.php} | 4 ++-- database/seeders/DatabaseSeeder.php | 2 ++ routes/api.php | 2 ++ 9 files changed, 44 insertions(+), 9 deletions(-) create mode 100644 app/Http/Controllers/JobdeskController.php rename database/migrations/{2024_11_21_140428_create_job_desk_table.php => 2024_11_23_124844_create_jobdesks_table.php} (87%) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php new file mode 100644 index 0000000..3bd0ff9 --- /dev/null +++ b/app/Http/Controllers/JobdeskController.php @@ -0,0 +1,20 @@ +paginate(25); + return response()->json($jobdesk); + } + + public function show(Jobdesk $jobdesk) + { + return response()->json($jobdesk); + } +} diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 7a47cb8..185c19e 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -3,7 +3,6 @@ namespace App\Http\Controllers; use App\Models\Order; -use App\Models\Customer; use Illuminate\Http\Request; class OrderController extends Controller @@ -19,7 +18,7 @@ class OrderController extends Controller ]; public function index() { - $orders = Order::with('customer')->paginate(25); + $orders = Order::with('customer', 'jobdesks')->paginate(25); return response()->json($orders); } diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 26f7519..41df55a 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -35,6 +35,6 @@ public function orders() public function jobDesks() { - return $this->hasMany(JobDesk::class); + return $this->hasMany(Jobdesk::class); } } diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php index 751755b..73eb8e3 100644 --- a/app/Models/JobDesk.php +++ b/app/Models/JobDesk.php @@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class JobDesk extends Model +class Jobdesk extends Model { use HasFactory; diff --git a/app/Models/Order.php b/app/Models/Order.php index 2e7243b..9350a69 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -27,4 +27,9 @@ public function customer() { return $this->belongsTo(Customer::class); } + + public function jobdesks() + { + return $this->hasMany(Jobdesk::class); + } } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 406bbc4..0e60f2a 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -2,12 +2,14 @@ namespace Database\Factories; +use App\Models\Order; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\JobDesk> + * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Jobdesk> */ -class JobDeskFactory extends Factory +class JobdeskFactory extends Factory { /** * Define the model's default state. @@ -17,7 +19,12 @@ class JobDeskFactory extends Factory public function definition(): array { return [ - // + 'order_id' => fake()->numberBetween(1, 10), + 'user_id' => fake()->numberBetween(1, 10), + 'customer_id' => fake()->numberBetween(1, 10), + 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), + 'tanggal_pengerjaan' => fake()->date(), + 'status' => fake()->randomElement(['Pending', 'Progress', 'Selesai']), ]; } } diff --git a/database/migrations/2024_11_21_140428_create_job_desk_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php similarity index 87% rename from database/migrations/2024_11_21_140428_create_job_desk_table.php rename to database/migrations/2024_11_23_124844_create_jobdesks_table.php index 130ed2a..b6f9bb3 100644 --- a/database/migrations/2024_11_21_140428_create_job_desk_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('job_desk', function (Blueprint $table) { + Schema::create('jobdesks', function (Blueprint $table) { $table->id(); $table->string('customer_id'); $table->string('order_id'); @@ -29,6 +29,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('job_desk'); + Schema::dropIfExists('jobdesks'); } }; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 1335909..0cc6055 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -3,6 +3,7 @@ namespace Database\Seeders; use App\Models\Customer; +use App\Models\Jobdesk; use App\Models\User; use App\Models\Order; use Illuminate\Database\Seeder; @@ -40,5 +41,6 @@ public function run(): void User::factory(100)->create(); Customer::factory(150)->create(); Order::factory(150)->create(); + Jobdesk::factory(100)->create(); } } diff --git a/routes/api.php b/routes/api.php index c6752f6..7e897aa 100644 --- a/routes/api.php +++ b/routes/api.php @@ -4,6 +4,7 @@ use Illuminate\Support\Facades\Route; use App\Http\Controllers\KaryawanController; use App\Http\Controllers\OrderController; +use App\Http\Controllers\JobdeskController; use App\Http\Controllers\CustomerController; use App\Http\Controllers\Auth\ProfileController; @@ -20,6 +21,7 @@ Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, + 'jobdesks' => JobdeskController::class, 'customers' => CustomerController::class ]); }); From f2b57417563be49718134f8fa076cc17dd528a34 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 26 Nov 2024 14:57:43 +0700 Subject: [PATCH 024/184] add filter order --- app/Http/Controllers/OrderController.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 185c19e..f4101a2 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -16,9 +16,21 @@ class OrderController extends Controller 'payment_method' => 'required', 'document' => 'required' ]; - public function index() + public function index(Request $request) { - $orders = Order::with('customer', 'jobdesks')->paginate(25); + // Ambil parameter 'customer' dari query string + $customerId = $request->query('customer'); + + // Jika ada ID customer, lakukan filter berdasarkan ID tersebut + if ($customerId) { + $orders = Order::with('customer', 'jobdesks') + ->where('customer_id', $customerId) + ->paginate(25); + } else { + // Jika tidak ada parameter, ambil semua pesanan + $orders = Order::with('customer', 'jobdesks')->paginate(25); + } + return response()->json($orders); } From 5f123bf271bdcc47432c6ba0acf0d0e8f8f62a71 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 28 Nov 2024 15:28:03 +0700 Subject: [PATCH 025/184] edit seeder --- app/Http/Controllers/CustomerController.php | 2 +- app/Http/Controllers/JobdeskController.php | 10 ++++++-- database/factories/JobDeskFactory.php | 2 +- database/seeders/DatabaseSeeder.php | 28 ++++++++++++++++++--- 4 files changed, 34 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index b932fae..43540e1 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -28,7 +28,7 @@ class CustomerController extends Controller public function index() { - $customers = Customer::paginate(25); + $customers = Customer::with('orders')->paginate(25); return response()->json($customers); } diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 3bd0ff9..e2d87f2 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -7,9 +7,15 @@ class JobdeskController extends Controller { - public function index() + public function index(Request $request) { - $jobdesk = Jobdesk::with('customer', 'order', 'user')->paginate(25); + $orderId = $request->query('order_id'); + + if ($orderId) { + $jobdesk = Jobdesk::with('customer', 'order', 'user')->where('order_id', $orderId)->paginate(25); + } else { + $jobdesk = Jobdesk::with('customer', 'order', 'user')->paginate(25); + } return response()->json($jobdesk); } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 0e60f2a..8e2e894 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -23,7 +23,7 @@ public function definition(): array 'user_id' => fake()->numberBetween(1, 10), 'customer_id' => fake()->numberBetween(1, 10), 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), - 'tanggal_pengerjaan' => fake()->date(), + 'tanggal_pengerjaan' => now(), 'status' => fake()->randomElement(['Pending', 'Progress', 'Selesai']), ]; } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 0cc6055..621d32b 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -38,9 +38,29 @@ public function run(): void 'password' => Hash::make('password'), ]); - User::factory(100)->create(); - Customer::factory(150)->create(); - Order::factory(150)->create(); - Jobdesk::factory(100)->create(); + // Membuat 30 pengguna + User::factory(30)->create(); + + // Membuat 5 customer + $customers = Customer::factory(5)->create(); + + foreach ($customers as $customer) { + // Membuat antara 2 hingga 10 order untuk setiap customer + $ordersCount = rand(2, 10); + $orders = Order::factory($ordersCount)->create(['customer_id' => $customer->id]); + + foreach ($orders as $order) { + // Membuat antara 2 hingga 10 jobdesk untuk setiap order + $jobdesksCount = rand(2, 10); + Jobdesk::factory($jobdesksCount)->create([ + 'order_id' => $order->id, + 'customer_id' => $customer->id + ]); + } + } + // User::factory(30)->create(); + // Customer::factory(50)->create(); + // Order::factory(10)->create(); + // Jobdesk::factory(10)->create(); } } From 3cf35475521a0aed09e1b0c762a12e3a04b19d9e Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 29 Nov 2024 13:46:24 +0700 Subject: [PATCH 026/184] handle search --- app/Http/Controllers/CustomerController.php | 19 +++++++++++++++++-- app/Http/Controllers/OrderController.php | 8 +++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 43540e1..c9d4556 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -26,9 +26,24 @@ class CustomerController extends Controller 'data_pajak_penjual' => 'required|numeric', ]; - public function index() + public function index(Request $request) { - $customers = Customer::with('orders')->paginate(25); + // Initialize the query + $query = Customer::with('orders'); + + // Filter by name if provided and longer than 3 characters + if ($request->has('name') && strlen($request->input('name')) > 3) { + $query->where('name', 'like', '%' . $request->input('name') . '%'); + } + + // Filter by phone if provided and longer than 3 characters + if ($request->has('phone') && strlen($request->input('phone')) > 3) { + $query->where('phone', 'like', '%' . $request->input('phone') . '%'); + } + + // Paginate the results + $customers = $query->paginate(25); + return response()->json($customers); } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index f4101a2..01ccc41 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -14,7 +14,8 @@ class OrderController extends Controller 'price' => 'required', 'paid' => 'required', 'payment_method' => 'required', - 'document' => 'required' + 'document' => 'required', + 'customer_id' => 'required|exists:customers,id', ]; public function index(Request $request) { @@ -50,8 +51,13 @@ public function update(Request $request, Order $order) public function store(Request $request) { + // Validate the incoming request $validatedData = $request->validate($this->validate); + + // Create the order with validated data $order = Order::create($validatedData); + + // Return the created order as a JSON response return response()->json($order); } From 59a0dde24ce10b40e1e4941e62c31f040dd71509 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 30 Nov 2024 14:43:12 +0700 Subject: [PATCH 027/184] ganti query url --- app/Http/Controllers/OrderController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 01ccc41..c863546 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -20,7 +20,7 @@ class OrderController extends Controller public function index(Request $request) { // Ambil parameter 'customer' dari query string - $customerId = $request->query('customer'); + $customerId = $request->query('customer_id'); // Jika ada ID customer, lakukan filter berdasarkan ID tersebut if ($customerId) { From a1a365e6a4a3ca2e3fc625d40e8c984a482a079b Mon Sep 17 00:00:00 2001 From: Imam Tri Date: Fri, 6 Dec 2024 22:07:11 +0700 Subject: [PATCH 028/184] Nambah Filter Customer --- app/Http/Controllers/CustomerController.php | 2 +- app/Http/Controllers/OrderController.php | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index c9d4556..f376fe3 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -32,7 +32,7 @@ public function index(Request $request) $query = Customer::with('orders'); // Filter by name if provided and longer than 3 characters - if ($request->has('name') && strlen($request->input('name')) > 3) { + if ($request->has('name') && strlen($request->input('name')) > 2) { $query->where('name', 'like', '%' . $request->input('name') . '%'); } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index c863546..399089e 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -22,14 +22,27 @@ public function index(Request $request) // Ambil parameter 'customer' dari query string $customerId = $request->query('customer_id'); + // if ($request->has('name') && strlen($request->input('name')) > 3) { + // $query->where('name', 'like', '%' . $request->input('name') . '%'); + // } + // Jika ada ID customer, lakukan filter berdasarkan ID tersebut if ($customerId) { $orders = Order::with('customer', 'jobdesks') ->where('customer_id', $customerId) ->paginate(25); } else { - // Jika tidak ada parameter, ambil semua pesanan - $orders = Order::with('customer', 'jobdesks')->paginate(25); + if ($request->has('name') && strlen($request->input('name')) > 2) { + $name = $request->input('name'); + $orders = Order::with('customer', 'jobdesks') + ->whereHas('customer', function ($query) use ($name) { + $query->where('name', 'like', '%' . $name . '%'); + }) + ->paginate(25); + } else { + // Jika tidak ada parameter, ambil semua pesanan + $orders = Order::with('customer', 'jobdesks')->paginate(25); + } } return response()->json($orders); From 651abebc6c8485ee0dcbc0590b63709d7bb50072 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 7 Dec 2024 13:20:21 +0700 Subject: [PATCH 029/184] add logic tanggal pengerjaan --- database/factories/JobDeskFactory.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 8e2e894..bafee66 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -18,13 +18,15 @@ class JobdeskFactory extends Factory */ public function definition(): array { + $status = fake()->randomElement(['Pending', 'Progress', 'Selesai']); return [ 'order_id' => fake()->numberBetween(1, 10), 'user_id' => fake()->numberBetween(1, 10), 'customer_id' => fake()->numberBetween(1, 10), 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), - 'tanggal_pengerjaan' => now(), - 'status' => fake()->randomElement(['Pending', 'Progress', 'Selesai']), + 'tanggal_pengerjaan' => now()->subDays(fake()->numberBetween(5, 10)), + 'tanggal_selesai' => $status === 'Selesai' ? now() : null, + 'status' => $status ]; } } From 595f834ee3810264156bdcc108e5799ebc371d8e Mon Sep 17 00:00:00 2001 From: Imam Tri Date: Tue, 10 Dec 2024 21:13:17 +0700 Subject: [PATCH 030/184] Add and point jobdesk masuk --- app/Http/Controllers/JobdeskController.php | 7 ++++++- database/factories/JobDeskFactory.php | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index e2d87f2..3d02162 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -10,11 +10,16 @@ class JobdeskController extends Controller public function index(Request $request) { $orderId = $request->query('order_id'); + $status = $request->query('status'); if ($orderId) { $jobdesk = Jobdesk::with('customer', 'order', 'user')->where('order_id', $orderId)->paginate(25); } else { - $jobdesk = Jobdesk::with('customer', 'order', 'user')->paginate(25); + if ($status) { + $jobdesk = Jobdesk::with('customer', 'order', 'user')->where('status', $status)->paginate(25); + } else { + $jobdesk = Jobdesk::with('customer', 'order', 'user')->paginate(25); + } } return response()->json($jobdesk); } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index bafee66..0b15506 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -18,7 +18,7 @@ class JobdeskFactory extends Factory */ public function definition(): array { - $status = fake()->randomElement(['Pending', 'Progress', 'Selesai']); + $status = fake()->randomElement(['Masuk', 'Progress', 'Selesai']); return [ 'order_id' => fake()->numberBetween(1, 10), 'user_id' => fake()->numberBetween(1, 10), From e1b727af6b5983b9fb458ce282bbfe4fe989474d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 13 Dec 2024 07:16:23 +0700 Subject: [PATCH 031/184] add dashboard controller --- app/Http/Controllers/Dashboard.php | 48 -------------------- app/Http/Controllers/DashboardController.php | 37 +++++++++++++++ routes/api.php | 2 + 3 files changed, 39 insertions(+), 48 deletions(-) delete mode 100644 app/Http/Controllers/Dashboard.php create mode 100644 app/Http/Controllers/DashboardController.php diff --git a/app/Http/Controllers/Dashboard.php b/app/Http/Controllers/Dashboard.php deleted file mode 100644 index fef0042..0000000 --- a/app/Http/Controllers/Dashboard.php +++ /dev/null @@ -1,48 +0,0 @@ -count(); + + // Menghitung total pendapatan dari semua order + // $totalRevenue = Order::sum('total_price'); + + // Menyiapkan data untuk response + $data = [ + 'total_customers' => $totalCustomers, + 'total_orders' => $totalOrders, + 'total_jobdesks' => $totalJobdesks, + 'total_jobdesks_masuk' => $totalJobdesksMasuk, + // 'total_revenue' => $totalRevenue, + ]; + + return response()->json($data); + } +} diff --git a/routes/api.php b/routes/api.php index 7e897aa..016d806 100644 --- a/routes/api.php +++ b/routes/api.php @@ -6,6 +6,7 @@ use App\Http\Controllers\OrderController; use App\Http\Controllers\JobdeskController; use App\Http\Controllers\CustomerController; +use App\Http\Controllers\DashboardController; use App\Http\Controllers\Auth\ProfileController; Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { @@ -18,6 +19,7 @@ }); Route::put('profile', [ProfileController::class, 'update']); + Route::get('dashboard', [DashboardController::class, 'index']); Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From 9810f500cc229f0db9459ffe73d38b4d6457750d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 13 Dec 2024 15:16:29 +0700 Subject: [PATCH 032/184] add dashboard data --- app/Http/Controllers/DashboardController.php | 23 ++++++++++++-------- database/factories/OrderFactory.php | 6 +++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 6f15e2e..9a26ede 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -5,7 +5,6 @@ use App\Models\Customer; use App\Models\Order; use App\Models\Jobdesk; -use Illuminate\Http\Request; class DashboardController extends Controller { @@ -16,20 +15,26 @@ public function index() { $totalCustomers = Customer::count(); $totalOrders = Order::count(); - $totalJobdesks = Jobdesk::count(); - // Jobdesk status == 'Masuk' - $totalJobdesksMasuk = Jobdesk::where('status', 'Masuk')->count(); - // Menghitung total pendapatan dari semua order - // $totalRevenue = Order::sum('total_price'); + $totalPendapatan = intval(Order::sum('paid')); + $totalBelumbayar = intval(Order::sum('price')) - intval(Order::sum('paid')); + + // Menghitung jobdesk berdasarkan status + $totalJobdesk = Jobdesk::select('status', \DB::raw('count(*) as count')) + ->groupBy('status') + ->pluck('count', 'status'); // Menyiapkan data untuk response $data = [ 'total_customers' => $totalCustomers, 'total_orders' => $totalOrders, - 'total_jobdesks' => $totalJobdesks, - 'total_jobdesks_masuk' => $totalJobdesksMasuk, - // 'total_revenue' => $totalRevenue, + 'total_pendapatan' => $totalPendapatan, + 'total_belumbayar' => $totalBelumbayar, + 'total_jobdesks' => [ + 'Masuk' => $totalJobdesk->get('Masuk', 0), + 'Progress' => $totalJobdesk->get('Progress', 0), + 'Selesai' => $totalJobdesk->get('Selesai', 0), + ], ]; return response()->json($data); diff --git a/database/factories/OrderFactory.php b/database/factories/OrderFactory.php index 7a3ca3b..629ad1e 100644 --- a/database/factories/OrderFactory.php +++ b/database/factories/OrderFactory.php @@ -24,13 +24,15 @@ public function definition(): array 'Pembuatan Surat Kuasa', 'Jasa Legalitas' ]; + $price = fake()->numberBetween(1000000, 10000000); + $paid = fake()->numberBetween(1000000, $price); return [ 'customer_id' => fake()->numberBetween(1, 10), 'order_date' => now(), 'service' => fake()->randomElement($layanan_notaris), - 'price' => fake()->numberBetween(100000, 10000000), + 'price' => $price, 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), - 'paid' => fake()->numberBetween(100000, 10000000), + 'paid' => $paid, 'document' => ['KTP', 'PBB', 'KK'] ]; } From c2b2d70c1279d159ebdba28538272537382c72e7 Mon Sep 17 00:00:00 2001 From: Imam Tri Date: Fri, 13 Dec 2024 22:22:31 +0700 Subject: [PATCH 033/184] Tambah data karyawan --- app/Http/Controllers/DashboardController.php | 3 ++ app/Http/Controllers/OrderController.php | 47 ++++++++++++-------- database/factories/JobDeskFactory.php | 3 +- database/seeders/DatabaseSeeder.php | 4 +- 4 files changed, 35 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 9a26ede..6b37360 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -5,6 +5,7 @@ use App\Models\Customer; use App\Models\Order; use App\Models\Jobdesk; +use App\Models\User; class DashboardController extends Controller { @@ -15,6 +16,7 @@ public function index() { $totalCustomers = Customer::count(); $totalOrders = Order::count(); + $totalKaryawan = User::count(); $totalPendapatan = intval(Order::sum('paid')); $totalBelumbayar = intval(Order::sum('price')) - intval(Order::sum('paid')); @@ -30,6 +32,7 @@ public function index() 'total_orders' => $totalOrders, 'total_pendapatan' => $totalPendapatan, 'total_belumbayar' => $totalBelumbayar, + 'total_karyawan' => $totalKaryawan, 'total_jobdesks' => [ 'Masuk' => $totalJobdesk->get('Masuk', 0), 'Progress' => $totalJobdesk->get('Progress', 0), diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 399089e..2351ab0 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -19,32 +19,41 @@ class OrderController extends Controller ]; public function index(Request $request) { - // Ambil parameter 'customer' dari query string + // Ambil parameter query dari request $customerId = $request->query('customer_id'); + $name = $request->query('name'); + $status = $request->query('status'); - // if ($request->has('name') && strlen($request->input('name')) > 3) { - // $query->where('name', 'like', '%' . $request->input('name') . '%'); - // } + // Mulai query dasar + $query = Order::with('customer', 'jobdesks'); - // Jika ada ID customer, lakukan filter berdasarkan ID tersebut + // Filter berdasarkan customer_id jika ada if ($customerId) { - $orders = Order::with('customer', 'jobdesks') - ->where('customer_id', $customerId) - ->paginate(25); + $query->where('customer_id', $customerId); + } + + // Filter berdasarkan nama customer jika parameter name diberikan dan panjangnya > 2 + if ($name && strlen($name) > 2) { + $query->whereHas('customer', function ($query) use ($name) { + $query->where('name', 'like', '%' . $name . '%'); + }); + } + + if ($status) { + // Jika semua status di dalam jobdesk sudah selesai + $query->whereHas('jobdesks', function ($query) use ($status) { + $query->where('status', $status); + }); } else { - if ($request->has('name') && strlen($request->input('name')) > 2) { - $name = $request->input('name'); - $orders = Order::with('customer', 'jobdesks') - ->whereHas('customer', function ($query) use ($name) { - $query->where('name', 'like', '%' . $name . '%'); - }) - ->paginate(25); - } else { - // Jika tidak ada parameter, ambil semua pesanan - $orders = Order::with('customer', 'jobdesks')->paginate(25); - } + // Jika semua status di dalam jobdesk belum selesai + $query->whereHas('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + }); } + // Paginate hasil + $orders = $query->paginate(25); + return response()->json($orders); } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 0b15506..699016d 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -18,7 +18,8 @@ class JobdeskFactory extends Factory */ public function definition(): array { - $status = fake()->randomElement(['Masuk', 'Progress', 'Selesai']); + $status = random_int(1, 100) <= 80 ? 'Selesai' : fake()->randomElement(['Masuk', 'Progress']); + return [ 'order_id' => fake()->numberBetween(1, 10), 'user_id' => fake()->numberBetween(1, 10), diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 621d32b..4e7f3f9 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -39,10 +39,10 @@ public function run(): void ]); // Membuat 30 pengguna - User::factory(30)->create(); + User::factory(25)->create(); // Membuat 5 customer - $customers = Customer::factory(5)->create(); + $customers = Customer::factory(35)->create(); foreach ($customers as $customer) { // Membuat antara 2 hingga 10 order untuk setiap customer From 79047e0bb279c0ef924444a68f5fe683df9b8b18 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 14 Dec 2024 09:34:01 +0700 Subject: [PATCH 034/184] add bulanan in array --- app/Http/Controllers/DashboardController.php | 9 +++++++-- database/factories/OrderFactory.php | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 6b37360..ca8dd1f 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -19,7 +19,10 @@ public function index() $totalKaryawan = User::count(); $totalPendapatan = intval(Order::sum('paid')); - $totalBelumbayar = intval(Order::sum('price')) - intval(Order::sum('paid')); + $pendapatanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('paid')); + $totalTagihan = intval(Order::sum('price')); + $totalTagihanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('price')); + $totalBelumbayar = $totalTagihan - $totalPendapatan; // Menghitung jobdesk berdasarkan status $totalJobdesk = Jobdesk::select('status', \DB::raw('count(*) as count')) @@ -31,7 +34,9 @@ public function index() 'total_customers' => $totalCustomers, 'total_orders' => $totalOrders, 'total_pendapatan' => $totalPendapatan, - 'total_belumbayar' => $totalBelumbayar, + 'pendapatan_bulan_ini' => $pendapatanBulanIni, + 'total_tagihan' => $totalTagihan, + 'total_tagihan_bulan_ini' => $totalTagihanBulanIni, 'total_karyawan' => $totalKaryawan, 'total_jobdesks' => [ 'Masuk' => $totalJobdesk->get('Masuk', 0), diff --git a/database/factories/OrderFactory.php b/database/factories/OrderFactory.php index 629ad1e..b2dfebe 100644 --- a/database/factories/OrderFactory.php +++ b/database/factories/OrderFactory.php @@ -26,9 +26,10 @@ public function definition(): array ]; $price = fake()->numberBetween(1000000, 10000000); $paid = fake()->numberBetween(1000000, $price); + $order_date = fake()->dateTimeBetween('-6 months', 'now'); return [ 'customer_id' => fake()->numberBetween(1, 10), - 'order_date' => now(), + 'order_date' => $order_date, 'service' => fake()->randomElement($layanan_notaris), 'price' => $price, 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), From b2b6d810215a9caee9db6ac26b75a96194cbc748 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 14 Dec 2024 13:34:05 +0700 Subject: [PATCH 035/184] add setting endpoin --- app/Http/Controllers/SettingController.php | 138 ++++++++++++++++++ app/Http/Requests/StoreSettingRequest.php | 38 +++++ app/Http/Requests/UpdateSettingRequest.php | 38 +++++ app/Models/Setting.php | 15 ++ app/Policies/SettingPolicy.php | 66 +++++++++ database/factories/SettingFactory.php | 28 ++++ ...024_12_14_102650_create_settings_table.php | 29 ++++ database/seeders/SettingSeeder.php | 17 +++ routes/api.php | 5 +- 9 files changed, 372 insertions(+), 2 deletions(-) create mode 100644 app/Http/Controllers/SettingController.php create mode 100644 app/Http/Requests/StoreSettingRequest.php create mode 100644 app/Http/Requests/UpdateSettingRequest.php create mode 100644 app/Models/Setting.php create mode 100644 app/Policies/SettingPolicy.php create mode 100644 database/factories/SettingFactory.php create mode 100644 database/migrations/2024_12_14_102650_create_settings_table.php create mode 100644 database/seeders/SettingSeeder.php diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php new file mode 100644 index 0000000..f8ba37a --- /dev/null +++ b/app/Http/Controllers/SettingController.php @@ -0,0 +1,138 @@ +json($settings); + } + + /** + * Store or update settings in storage. + */ + public function store(StoreSettingRequest $request) + { + $validatedData = $request->validated(); + $settingsToSave = []; + + // Handle file uploads + if ($request->hasFile('favicon')) { + $faviconPath = $request->file('favicon')->store('favicons', 'public'); + $settingsToSave['favicon'] = $faviconPath; + } + + if ($request->hasFile('pdf_sample')) { + $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); + $settingsToSave['pdf_sample'] = $pdfPath; + } + + // Save or update each setting + foreach ($validatedData as $key => $value) { + $settingsToSave[$key] = $value; // Add other validated settings + Setting::updateOrCreate( + ['setting_key' => $key], + ['setting_value' => $value] + ); + } + + return response()->json([ + 'success' => true, + 'message' => 'Settings saved successfully.', + 'data' => $settingsToSave + ], 201); + } + + /** + * Display the specified setting. + */ + public function show($key) + { + $setting = Setting::where('setting_key', $key)->first(); + + if (!$setting) { + return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); + } + + return response()->json($setting); + } + + /** + * Update the specified setting in storage. + */ + public function update(UpdateSettingRequest $request, $key) + { + $setting = Setting::where('setting_key', $key)->first(); + + if (!$setting) { + return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); + } + + $validatedData = $request->validated(); + $settingsToUpdate = []; + + // Handle file uploads + if ($request->hasFile('favicon')) { + if ($setting->setting_key === 'favicon') { + Storage::disk('public')->delete($setting->setting_value); + } + $faviconPath = $request->file('favicon')->store('favicons', 'public'); + $settingsToUpdate['favicon'] = $faviconPath; + } + + if ($request->hasFile('pdf_sample')) { + if ($setting->setting_key === 'pdf_sample') { + Storage::disk('public')->delete($setting->setting_value); + } + $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); + $settingsToUpdate['pdf_sample'] = $pdfPath; + } + + // Update the setting value + foreach ($validatedData as $key => $value) { + $settingsToUpdate[$key] = $value; + $setting->update(['setting_value' => $value]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Setting updated successfully.', + 'data' => $setting + ], 200); + } + + /** + * Remove the specified setting from storage. + */ + public function destroy($key) + { + $setting = Setting::where('setting_key', $key)->first(); + + if (!$setting) { + return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); + } + + // Delete associated file if exists + if ($setting->setting_value) { + Storage::disk('public')->delete($setting->setting_value); + } + + // Delete the setting record + $setting->delete(); + + return response()->json([ + 'success' => true, + 'message' => 'Setting deleted successfully.' + ], 200); + } +} diff --git a/app/Http/Requests/StoreSettingRequest.php b/app/Http/Requests/StoreSettingRequest.php new file mode 100644 index 0000000..e4d3925 --- /dev/null +++ b/app/Http/Requests/StoreSettingRequest.php @@ -0,0 +1,38 @@ + 'nullable|file|mimes:ico,png,jpg,jpeg|max:2048', + 'app_name' => 'nullable|string|max:255', // Changed to nullable for flexibility + 'app_description' => 'nullable|string|max:500', // Changed to nullable for flexibility + 'alamat' => 'nullable|string|max:255', // Changed to nullable for flexibility + 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', + 'email' => 'nullable|email|max:255', + ]; + } + + public function authorize() + { + return true; // Ensure that the user is authorized to make this request + } + + public function messages() + { + return [ + 'favicon.mimes' => 'Favicon must be a file of type: ico, png, jpg, jpeg.', + 'app_name.max' => 'App name may not be greater than :max characters.', + 'app_description.max' => 'App description may not be greater than :max characters.', + 'alamat.max' => 'Address may not be greater than :max characters.', + 'pdf_sample.mimes' => 'PDF sample must be a file of type: pdf.', + 'email.email' => 'Email must be a valid email address.', + 'email.max' => 'Email may not be greater than :max characters.', + ]; + } +} diff --git a/app/Http/Requests/UpdateSettingRequest.php b/app/Http/Requests/UpdateSettingRequest.php new file mode 100644 index 0000000..62d42c4 --- /dev/null +++ b/app/Http/Requests/UpdateSettingRequest.php @@ -0,0 +1,38 @@ + 'nullable|file|mimes:ico,png,jpg,jpeg|max:2048', + 'app_name' => 'nullable|string|max:255', + 'app_description' => 'nullable|string|max:500', + 'alamat' => 'nullable|string|max:255', + 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', + 'email' => 'nullable|email|max:255', + ]; + } + + public function authorize() + { + return true; // Ensure that the user is authorized to make this request + } + + public function messages() + { + return [ + 'favicon.mimes' => 'Favicon must be a file of type: ico, png, jpg, jpeg.', + 'app_name.max' => 'App name may not be greater than :max characters.', + 'app_description.max' => 'App description may not be greater than :max characters.', + 'alamat.max' => 'Address may not be greater than :max characters.', + 'pdf_sample.mimes' => 'PDF sample must be a file of type: pdf.', + 'email.email' => 'Email must be a valid email address.', + 'email.max' => 'Email may not be greater than :max characters.', + ]; + } +} diff --git a/app/Models/Setting.php b/app/Models/Setting.php new file mode 100644 index 0000000..1a3e32e --- /dev/null +++ b/app/Models/Setting.php @@ -0,0 +1,15 @@ +is_admin === 1; + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Setting $setting): bool + { + // + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Setting $setting): bool + { + // + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Setting $setting): bool + { + // + } +} diff --git a/database/factories/SettingFactory.php b/database/factories/SettingFactory.php new file mode 100644 index 0000000..a575c9f --- /dev/null +++ b/database/factories/SettingFactory.php @@ -0,0 +1,28 @@ + + */ +class SettingFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + ['setting_key' => 'favicon', 'setting_value' => 'path/to/favicon.ico'], + ['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT'], + ['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online'], + ['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], + ['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf'], + ['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com'], + ]; + } +} diff --git a/database/migrations/2024_12_14_102650_create_settings_table.php b/database/migrations/2024_12_14_102650_create_settings_table.php new file mode 100644 index 0000000..f65cea4 --- /dev/null +++ b/database/migrations/2024_12_14_102650_create_settings_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('setting_key')->unique(); // Unique key for the setting + $table->text('setting_value')->nullable(); // Value of the setting + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('settings'); + } +}; diff --git a/database/seeders/SettingSeeder.php b/database/seeders/SettingSeeder.php new file mode 100644 index 0000000..9a6d9b6 --- /dev/null +++ b/database/seeders/SettingSeeder.php @@ -0,0 +1,17 @@ +get('/user', function (Request $request) { @@ -18,12 +19,12 @@ return $request->user(); }); Route::put('profile', [ProfileController::class, 'update']); - Route::get('dashboard', [DashboardController::class, 'index']); Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, 'jobdesks' => JobdeskController::class, - 'customers' => CustomerController::class + 'customers' => CustomerController::class, + 'settings' => SettingController::class ]); }); From 066e141e58cc6a99ae7e8b5a4fb3aa79b2b2577b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 14 Dec 2024 15:08:39 +0700 Subject: [PATCH 036/184] gabungin controller --- app/Http/Controllers/SettingController.php | 52 +++++++++++++--------- app/Http/Requests/StoreSettingRequest.php | 38 ---------------- app/Http/Requests/UpdateSettingRequest.php | 38 ---------------- database/factories/SettingFactory.php | 1 - 4 files changed, 31 insertions(+), 98 deletions(-) delete mode 100644 app/Http/Requests/StoreSettingRequest.php delete mode 100644 app/Http/Requests/UpdateSettingRequest.php diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index f8ba37a..a0cfd85 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -2,13 +2,15 @@ namespace App\Http\Controllers; +use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use App\Models\Setting; -use App\Http\Requests\StoreSettingRequest; -use App\Http\Requests\UpdateSettingRequest; use Illuminate\Support\Facades\Storage; +use Illuminate\Http\Request; class SettingController extends Controller { + use AuthorizesRequests; + /** * Display the settings. */ @@ -21,16 +23,21 @@ public function index() /** * Store or update settings in storage. */ - public function store(StoreSettingRequest $request) + public function store(Request $request) { - $validatedData = $request->validated(); - $settingsToSave = []; - - // Handle file uploads - if ($request->hasFile('favicon')) { - $faviconPath = $request->file('favicon')->store('favicons', 'public'); - $settingsToSave['favicon'] = $faviconPath; + // Define validation rules + $validatedData = $request->validate([ + 'app_name' => 'nullable|string|max:255', + 'app_description' => 'nullable|string|max:500', + 'alamat' => 'nullable|string|max:255', + 'pdf_sample' => 'nullable', + 'email' => 'nullable|email|max:255', + ]); + + if (is_string($request->pdf_sample)) { + unset($validatedData['pdf_sample']); } + $settingsToSave = []; if ($request->hasFile('pdf_sample')) { $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); @@ -70,7 +77,7 @@ public function show($key) /** * Update the specified setting in storage. */ - public function update(UpdateSettingRequest $request, $key) + public function update(Request $request, $key) { $setting = Setting::where('setting_key', $key)->first(); @@ -78,18 +85,21 @@ public function update(UpdateSettingRequest $request, $key) return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); } - $validatedData = $request->validated(); - $settingsToUpdate = []; - - // Handle file uploads - if ($request->hasFile('favicon')) { - if ($setting->setting_key === 'favicon') { - Storage::disk('public')->delete($setting->setting_value); - } - $faviconPath = $request->file('favicon')->store('favicons', 'public'); - $settingsToUpdate['favicon'] = $faviconPath; + // Define validation rules + $validatedData = $request->validate([ + 'app_name' => 'nullable|string|max:255', + 'app_description' => 'nullable|string|max:500', + 'alamat' => 'nullable|string|max:255', + 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', + 'email' => 'nullable|email|max:255', + ]); + + if (is_string($request->pdf_sample)) { + unset($validatedData['pdf_sample']); } + $settingsToUpdate = []; + if ($request->hasFile('pdf_sample')) { if ($setting->setting_key === 'pdf_sample') { Storage::disk('public')->delete($setting->setting_value); diff --git a/app/Http/Requests/StoreSettingRequest.php b/app/Http/Requests/StoreSettingRequest.php deleted file mode 100644 index e4d3925..0000000 --- a/app/Http/Requests/StoreSettingRequest.php +++ /dev/null @@ -1,38 +0,0 @@ - 'nullable|file|mimes:ico,png,jpg,jpeg|max:2048', - 'app_name' => 'nullable|string|max:255', // Changed to nullable for flexibility - 'app_description' => 'nullable|string|max:500', // Changed to nullable for flexibility - 'alamat' => 'nullable|string|max:255', // Changed to nullable for flexibility - 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', - 'email' => 'nullable|email|max:255', - ]; - } - - public function authorize() - { - return true; // Ensure that the user is authorized to make this request - } - - public function messages() - { - return [ - 'favicon.mimes' => 'Favicon must be a file of type: ico, png, jpg, jpeg.', - 'app_name.max' => 'App name may not be greater than :max characters.', - 'app_description.max' => 'App description may not be greater than :max characters.', - 'alamat.max' => 'Address may not be greater than :max characters.', - 'pdf_sample.mimes' => 'PDF sample must be a file of type: pdf.', - 'email.email' => 'Email must be a valid email address.', - 'email.max' => 'Email may not be greater than :max characters.', - ]; - } -} diff --git a/app/Http/Requests/UpdateSettingRequest.php b/app/Http/Requests/UpdateSettingRequest.php deleted file mode 100644 index 62d42c4..0000000 --- a/app/Http/Requests/UpdateSettingRequest.php +++ /dev/null @@ -1,38 +0,0 @@ - 'nullable|file|mimes:ico,png,jpg,jpeg|max:2048', - 'app_name' => 'nullable|string|max:255', - 'app_description' => 'nullable|string|max:500', - 'alamat' => 'nullable|string|max:255', - 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', - 'email' => 'nullable|email|max:255', - ]; - } - - public function authorize() - { - return true; // Ensure that the user is authorized to make this request - } - - public function messages() - { - return [ - 'favicon.mimes' => 'Favicon must be a file of type: ico, png, jpg, jpeg.', - 'app_name.max' => 'App name may not be greater than :max characters.', - 'app_description.max' => 'App description may not be greater than :max characters.', - 'alamat.max' => 'Address may not be greater than :max characters.', - 'pdf_sample.mimes' => 'PDF sample must be a file of type: pdf.', - 'email.email' => 'Email must be a valid email address.', - 'email.max' => 'Email may not be greater than :max characters.', - ]; - } -} diff --git a/database/factories/SettingFactory.php b/database/factories/SettingFactory.php index a575c9f..9bf6f79 100644 --- a/database/factories/SettingFactory.php +++ b/database/factories/SettingFactory.php @@ -17,7 +17,6 @@ class SettingFactory extends Factory public function definition(): array { return [ - ['setting_key' => 'favicon', 'setting_value' => 'path/to/favicon.ico'], ['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT'], ['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online'], ['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], From 039678575c09894729a19bd5ba89e24313d3df6e Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 15 Dec 2024 11:11:26 +0700 Subject: [PATCH 037/184] fix status request --- app/Http/Controllers/OrderController.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 2351ab0..633c609 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -23,6 +23,7 @@ public function index(Request $request) $customerId = $request->query('customer_id'); $name = $request->query('name'); $status = $request->query('status'); + $status = ($status === 'Arsip') ? 'Selesai' : $status; // Mulai query dasar $query = Order::with('customer', 'jobdesks'); @@ -40,12 +41,10 @@ public function index(Request $request) } if ($status) { - // Jika semua status di dalam jobdesk sudah selesai - $query->whereHas('jobdesks', function ($query) use ($status) { - $query->where('status', $status); + $query->whereDoesntHave('jobdesks', function ($query) use ($status) { + $query->where('status', '!=', $status); }); } else { - // Jika semua status di dalam jobdesk belum selesai $query->whereHas('jobdesks', function ($query) { $query->where('status', '!=', 'Selesai'); }); From bcbffc9d8f95b86e90c3803f3b210872f48edc5e Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 16 Dec 2024 14:33:36 +0700 Subject: [PATCH 038/184] add pending jobdesk --- app/Notifications/PendingJobdesk.php | 54 ++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 app/Notifications/PendingJobdesk.php diff --git a/app/Notifications/PendingJobdesk.php b/app/Notifications/PendingJobdesk.php new file mode 100644 index 0000000..6f313e5 --- /dev/null +++ b/app/Notifications/PendingJobdesk.php @@ -0,0 +1,54 @@ + + */ + public function via(object $notifiable): array + { + return ['mail']; + } + + /** + * Get the mail representation of the notification. + */ + public function toMail(object $notifiable): MailMessage + { + return (new MailMessage) + ->line('The introduction to the notification.') + ->action('Notification Action', url('/')) + ->line('Thank you for using our application!'); + } + + /** + * Get the array representation of the notification. + * + * @return array + */ + public function toArray(object $notifiable): array + { + return [ + // + ]; + } +} From 20b16fe1a288c474efe73eef8e312f049f621d4c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 17 Dec 2024 14:56:39 +0700 Subject: [PATCH 039/184] add notification table --- app/Http/Controllers/KaryawanController.php | 22 +++++++++++++ app/Notifications/PendingJobdesk.php | 18 +++++++---- database/factories/JobDeskFactory.php | 2 +- ...2_17_145546_create_notifications_table.php | 31 +++++++++++++++++++ routes/api.php | 1 + 5 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 database/migrations/2024_12_17_145546_create_notifications_table.php diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 37c9f23..5964d6d 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -6,6 +6,9 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use App\Models\User; +use App\Models\Jobdesk; +use App\Notifications\PendingJobdesk; + class KaryawanController extends Controller { @@ -80,6 +83,25 @@ public function update(Request $request, $id) ], 200); } + public function sendJobdeskReminder(Request $request) + { + $request->validate([ + 'jobdesk_id' => 'required|integer|exists:jobdesks,id', + 'title' => 'required|string|max:255', + ]); + + $user = User::find($request->user()->id); + $jobdesk = [ + 'id' => $request->jobdesk_id, + 'title' => $request->title, + ]; + + // Kirim notifikasi + $user->notify(new PendingJobdesk($jobdesk)); + + return response()->json(['message' => 'Notifikasi jobdesk telah dikirim!']); + } + public function destroy($id) { $user = User::findOrFail($id); diff --git a/app/Notifications/PendingJobdesk.php b/app/Notifications/PendingJobdesk.php index 6f313e5..43f19ea 100644 --- a/app/Notifications/PendingJobdesk.php +++ b/app/Notifications/PendingJobdesk.php @@ -14,9 +14,11 @@ class PendingJobdesk extends Notification /** * Create a new notification instance. */ - public function __construct() + protected $jobdesk; + + public function __construct($jobdesk) { - // + $this->jobdesk = $jobdesk; } /** @@ -32,12 +34,16 @@ public function via(object $notifiable): array /** * Get the mail representation of the notification. */ - public function toMail(object $notifiable): MailMessage + public function toMail($notifiable) { return (new MailMessage) - ->line('The introduction to the notification.') - ->action('Notification Action', url('/')) - ->line('Thank you for using our application!'); + ->subject('Pemberitahuan: Jobdesk Belum Diambil') + ->greeting('Halo ' . $notifiable->name . '!') + ->line('Kami ingin mengingatkan Anda bahwa ada jobdesk yang belum Anda ambil:') + ->line('Jobdesk: ' . $this->jobdesk['title']) + ->line('Deskripsi: ' . $this->jobdesk['description']) + ->action('Ambil Jobdesk', url('/jobdesk/' . $this->jobdesk['id'])) + ->line('Terima kasih atas perhatian Anda!'); } /** diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 699016d..ab91aab 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -25,7 +25,7 @@ public function definition(): array 'user_id' => fake()->numberBetween(1, 10), 'customer_id' => fake()->numberBetween(1, 10), 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), - 'tanggal_pengerjaan' => now()->subDays(fake()->numberBetween(5, 10)), + 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, 'tanggal_selesai' => $status === 'Selesai' ? now() : null, 'status' => $status ]; diff --git a/database/migrations/2024_12_17_145546_create_notifications_table.php b/database/migrations/2024_12_17_145546_create_notifications_table.php new file mode 100644 index 0000000..d738032 --- /dev/null +++ b/database/migrations/2024_12_17_145546_create_notifications_table.php @@ -0,0 +1,31 @@ +uuid('id')->primary(); + $table->string('type'); + $table->morphs('notifiable'); + $table->text('data'); + $table->timestamp('read_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('notifications'); + } +}; diff --git a/routes/api.php b/routes/api.php index e0e462b..3a4ad10 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,6 +18,7 @@ Route::get('profile', function (Request $request) { return $request->user(); }); + Route::post('/send-jobdesk-reminder', [KaryawanController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('dashboard', [DashboardController::class, 'index']); Route::apiResources([ From 003eeb2a723ef74620935b09a4cc34e51a0f27b3 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 17 Dec 2024 15:32:02 +0700 Subject: [PATCH 040/184] fix jobdesk end point --- app/Http/Controllers/KaryawanController.php | 12 ++++++------ app/Notifications/PendingJobdesk.php | 16 ++++++++-------- routes/api.php | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 5964d6d..38b73e5 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -87,17 +87,17 @@ public function sendJobdeskReminder(Request $request) { $request->validate([ 'jobdesk_id' => 'required|integer|exists:jobdesks,id', - 'title' => 'required|string|max:255', ]); - $user = User::find($request->user()->id); - $jobdesk = [ - 'id' => $request->jobdesk_id, - 'title' => $request->title, + $jobdesk = Jobdesk::find($request->jobdesk_id); + $user = User::find($jobdesk->user_id); + $data = [ + 'jobdesk_id' => $request->jobdesk_id, + 'user_id' => $user->id, ]; // Kirim notifikasi - $user->notify(new PendingJobdesk($jobdesk)); + $user->notify(new PendingJobdesk($data)); return response()->json(['message' => 'Notifikasi jobdesk telah dikirim!']); } diff --git a/app/Notifications/PendingJobdesk.php b/app/Notifications/PendingJobdesk.php index 43f19ea..27ae109 100644 --- a/app/Notifications/PendingJobdesk.php +++ b/app/Notifications/PendingJobdesk.php @@ -14,11 +14,11 @@ class PendingJobdesk extends Notification /** * Create a new notification instance. */ - protected $jobdesk; + protected $data; - public function __construct($jobdesk) + public function __construct($data) { - $this->jobdesk = $jobdesk; + $this->data = $data; } /** @@ -28,7 +28,7 @@ public function __construct($jobdesk) */ public function via(object $notifiable): array { - return ['mail']; + return ['mail', 'database']; } /** @@ -40,9 +40,8 @@ public function toMail($notifiable) ->subject('Pemberitahuan: Jobdesk Belum Diambil') ->greeting('Halo ' . $notifiable->name . '!') ->line('Kami ingin mengingatkan Anda bahwa ada jobdesk yang belum Anda ambil:') - ->line('Jobdesk: ' . $this->jobdesk['title']) - ->line('Deskripsi: ' . $this->jobdesk['description']) - ->action('Ambil Jobdesk', url('/jobdesk/' . $this->jobdesk['id'])) + ->line('Jobdesk: ' . $this->data['jobdesk_id']) + ->action('Ambil Jobdesk', url('/jobdesk/' . $this->data['jobdesk_id'])) ->line('Terima kasih atas perhatian Anda!'); } @@ -54,7 +53,8 @@ public function toMail($notifiable) public function toArray(object $notifiable): array { return [ - // + 'jobdesk' => $this->data['jobdesk_id'], + 'message' => 'Pemberitahuan: Jobdesk #' . $this->data['jobdesk_id'] . ' Belum Diambil' ]; } } diff --git a/routes/api.php b/routes/api.php index 3a4ad10..8cbc558 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,7 +18,7 @@ Route::get('profile', function (Request $request) { return $request->user(); }); - Route::post('/send-jobdesk-reminder', [KaryawanController::class, 'sendJobdeskReminder']); + Route::post('jobdesk-reminder', [KaryawanController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('dashboard', [DashboardController::class, 'index']); Route::apiResources([ From 3dd836d5b336e9f12892065714034a11af303095 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 17 Dec 2024 20:36:26 +0700 Subject: [PATCH 041/184] add all karyawan response --- app/Http/Controllers/KaryawanController.php | 9 +++++++-- database/factories/JobDeskFactory.php | 2 +- .../2024_11_23_124844_create_jobdesks_table.php | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 38b73e5..20fc949 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -14,9 +14,14 @@ class KaryawanController extends Controller { use AuthorizesRequests; - public function index() + public function index(Request $request) { - $user = User::paginate(25); + $page = $request->query('page'); + if ($page === 'all') { + $user = User::all(); + } else { + $user = User::paginate(25); + } return response()->json($user); } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index ab91aab..21ee5be 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -22,7 +22,7 @@ public function definition(): array return [ 'order_id' => fake()->numberBetween(1, 10), - 'user_id' => fake()->numberBetween(1, 10), + 'user_id' => $status !== 'Masuk' ? fake()->numberBetween(1, 10) : null, 'customer_id' => fake()->numberBetween(1, 10), 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php index b6f9bb3..a211eb4 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -15,7 +15,7 @@ public function up(): void $table->id(); $table->string('customer_id'); $table->string('order_id'); - $table->string('user_id'); + $table->string('user_id')->nullable(); $table->string('jobdesk'); $table->date('tanggal_pengerjaan')->nullable(); $table->date('tanggal_selesai')->nullable(); From d26936cba2481a67982098988c80f2e93feabe35 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 17 Dec 2024 22:04:47 +0700 Subject: [PATCH 042/184] add update & store --- app/Http/Controllers/JobdeskController.php | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 3d02162..1a939e8 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -24,8 +24,36 @@ public function index(Request $request) return response()->json($jobdesk); } + public function store(Request $request) + { + $validatedData = $request->validate([ + 'order_id' => 'required|exists:orders,id', + 'user_id' => 'required|exists:users,id', + 'tanggal_pengerjaan' => 'required|date', + 'tanggal_selesai' => 'required|date', + 'status' => 'required', + ]); + $jobdesk = Jobdesk::create($validatedData); + return response()->json($jobdesk); + } + + public function update(Request $request, Jobdesk $jobdesk) + { + $jobdesk = Jobdesk::find($jobdesk->id); + $validatedData = $request->validate([ + 'order_id' => 'required|exists:orders,id', + 'user_id' => 'required|exists:users,id', + 'tanggal_pengerjaan' => 'required|date', + 'tanggal_selesai' => 'required|date', + 'status' => 'required', + ]); + $jobdesk->update($validatedData); + return response()->json($jobdesk); + } + public function show(Jobdesk $jobdesk) { + $jobdesk = Jobdesk::find($jobdesk->id)->load('customer', 'order', 'user'); return response()->json($jobdesk); } } From e478d7cd307685428f328a9d51d2c671be17dfad Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 18 Dec 2024 10:26:22 +0700 Subject: [PATCH 043/184] fix --- app/Http/Controllers/CustomerController.php | 18 ++++++++---- app/Http/Controllers/JobdeskController.php | 29 ++++++++++++++----- database/factories/JobDeskFactory.php | 2 +- ...024_11_23_124844_create_jobdesks_table.php | 2 +- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index f376fe3..cbf9ddd 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -28,17 +28,23 @@ class CustomerController extends Controller public function index(Request $request) { + // Validate input + $validated = $request->validate([ + 'name' => 'nullable|string|min:3', + 'phone' => 'nullable|string|min:4', + ]); + // Initialize the query $query = Customer::with('orders'); - // Filter by name if provided and longer than 3 characters - if ($request->has('name') && strlen($request->input('name')) > 2) { - $query->where('name', 'like', '%' . $request->input('name') . '%'); + // Filter by name if provided + if (!empty($validated['name'])) { + $query->where('name', 'like', '%' . $validated['name'] . '%'); } - // Filter by phone if provided and longer than 3 characters - if ($request->has('phone') && strlen($request->input('phone')) > 3) { - $query->where('phone', 'like', '%' . $request->input('phone') . '%'); + // Filter by phone if provided + if (!empty($validated['phone'])) { + $query->where('phone', 'like', '%' . $validated['phone'] . '%'); } // Paginate the results diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 3d02162..b9df1dd 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -11,21 +11,36 @@ public function index(Request $request) { $orderId = $request->query('order_id'); $status = $request->query('status'); + $name = $request->query('name'); // New parameter for employee name + // Initialize the query + $query = Jobdesk::with('customer', 'order', 'user'); + + // Filter by order_id if provided if ($orderId) { - $jobdesk = Jobdesk::with('customer', 'order', 'user')->where('order_id', $orderId)->paginate(25); - } else { - if ($status) { - $jobdesk = Jobdesk::with('customer', 'order', 'user')->where('status', $status)->paginate(25); - } else { - $jobdesk = Jobdesk::with('customer', 'order', 'user')->paginate(25); - } + $query->where('order_id', $orderId); + } + + // Filter by status if provided + if ($status) { + $query->where('status', $status); } + + if ($name && strlen($name) > 2) { + $query->whereHas('customer', function ($query) use ($name) { + $query->where('name', 'like', '%' . $name . '%'); + }); + } + + // Paginate the results + $jobdesk = $query->paginate(25); + return response()->json($jobdesk); } public function show(Jobdesk $jobdesk) { + $jobdesk = Jobdesk::find($jobdesk->id)->load('customer', 'order', 'user'); return response()->json($jobdesk); } } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index ab91aab..21ee5be 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -22,7 +22,7 @@ public function definition(): array return [ 'order_id' => fake()->numberBetween(1, 10), - 'user_id' => fake()->numberBetween(1, 10), + 'user_id' => $status !== 'Masuk' ? fake()->numberBetween(1, 10) : null, 'customer_id' => fake()->numberBetween(1, 10), 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php index b6f9bb3..a211eb4 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -15,7 +15,7 @@ public function up(): void $table->id(); $table->string('customer_id'); $table->string('order_id'); - $table->string('user_id'); + $table->string('user_id')->nullable(); $table->string('jobdesk'); $table->date('tanggal_pengerjaan')->nullable(); $table->date('tanggal_selesai')->nullable(); From 9b4979f5e82c0f36bb902778795792795b7b4861 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 18 Dec 2024 14:33:10 +0700 Subject: [PATCH 044/184] add date condition --- app/Http/Controllers/JobdeskController.php | 21 +++++++++++++---- app/Models/Setting.php | 3 ++- database/factories/SettingFactory.php | 27 ---------------------- database/seeders/DatabaseSeeder.php | 11 +++++---- 4 files changed, 26 insertions(+), 36 deletions(-) delete mode 100644 database/factories/SettingFactory.php diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index ea2262b..ae40a0d 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -43,10 +43,16 @@ public function store(Request $request) $validatedData = $request->validate([ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', - 'tanggal_pengerjaan' => 'required|date', - 'tanggal_selesai' => 'required|date', + 'tanggal_pengerjaan' => 'nullable', + 'tanggal_selesai' => 'nullable', 'status' => 'required', ]); + if (isset($validatedData['tanggal_pengerjaan'])) { + $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); + } + if (isset($validatedData['tanggal_selesai'])) { + $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); + } $jobdesk = Jobdesk::create($validatedData); return response()->json($jobdesk); } @@ -57,10 +63,17 @@ public function update(Request $request, Jobdesk $jobdesk) $validatedData = $request->validate([ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', - 'tanggal_pengerjaan' => 'required|date', - 'tanggal_selesai' => 'required|date', + 'tanggal_pengerjaan' => 'nullable', + 'tanggal_selesai' => 'nullable', 'status' => 'required', ]); + if (isset($validatedData['tanggal_pengerjaan'])) { + $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); + } + + if (isset($validatedData['tanggal_selesai'])) { + $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); + } $jobdesk->update($validatedData); return response()->json($jobdesk); } diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 1a3e32e..8b1ffa4 100644 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -2,12 +2,13 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Setting extends Model { + use HasFactory; protected $table = 'settings'; - protected $fillable = [ 'setting_key', 'setting_value' diff --git a/database/factories/SettingFactory.php b/database/factories/SettingFactory.php deleted file mode 100644 index 9bf6f79..0000000 --- a/database/factories/SettingFactory.php +++ /dev/null @@ -1,27 +0,0 @@ - - */ -class SettingFactory extends Factory -{ - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - return [ - ['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT'], - ['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online'], - ['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], - ['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf'], - ['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com'], - ]; - } -} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 4e7f3f9..f38f0cd 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -6,6 +6,7 @@ use App\Models\Jobdesk; use App\Models\User; use App\Models\Order; +use App\Models\Setting; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; use Pest\ArchPresets\Custom; @@ -58,9 +59,11 @@ public function run(): void ]); } } - // User::factory(30)->create(); - // Customer::factory(50)->create(); - // Order::factory(10)->create(); - // Jobdesk::factory(10)->create(); + + Setting::create(['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT']); + Setting::create(['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online']); + Setting::create(['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur']); + Setting::create(['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf']); + Setting::create(['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com']); } } From 818059aa319b868535494b42141879a5a809f0f6 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 19 Dec 2024 15:31:33 +0700 Subject: [PATCH 045/184] fix order controller --- app/Http/Controllers/OrderController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 633c609..ba5c1bd 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -44,10 +44,11 @@ public function index(Request $request) $query->whereDoesntHave('jobdesks', function ($query) use ($status) { $query->where('status', '!=', $status); }); + $query->whereHas('jobdesks'); } else { $query->whereHas('jobdesks', function ($query) { $query->where('status', '!=', 'Selesai'); - }); + })->orWhereDoesntHave('jobdesks'); } // Paginate hasil @@ -85,6 +86,7 @@ public function store(Request $request) public function destroy(Order $order) { $order = Order::find($order->id); + $order->jobdesks()->delete(); $order->delete(); return response()->json($order); } From c2ffb3beb3a4b3468f72f49210cd045e2ed0ffdf Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 20 Dec 2024 13:36:21 +0700 Subject: [PATCH 046/184] fix upload document --- app/Http/Controllers/OrderController.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index ba5c1bd..78ca17a 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -65,8 +65,29 @@ public function show(Order $order) public function update(Request $request, Order $order) { - $order = Order::find($order->id); + // Validasi dokumen jika ada + if ($request->hasFile('document')) { + $this->validate = [ + 'document' => 'required|mimes:pdf', + ]; + } + + // Validasi data yang diterima $validatedData = $request->validate($this->validate); + + // Cek dan hapus dokumen lama jika ada + if ($order->document) { + // Hapus dokumen lama dari storage + Storage::disk('public')->delete($order->document); + } + + // Menyimpan dokumen baru jika ada + if ($request->hasFile('document')) { + $filePath = $request->file('document')->store('documents', 'public'); + $validatedData['document'] = $filePath; // Simpan path file ke validated data + } + + // Update order dengan data yang sudah divalidasi $order->update($validatedData); return response()->json($order); } From f181fe0ac4bbb1cd700f626063461dca60908899 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 20 Dec 2024 14:09:10 +0700 Subject: [PATCH 047/184] fix lampiran --- app/Http/Controllers/OrderController.php | 24 +++++++++++-------- app/Models/Order.php | 3 ++- .../2024_11_06_033508_create_orders_table.php | 1 + 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 78ca17a..ce3a96c 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -4,6 +4,7 @@ use App\Models\Order; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; class OrderController extends Controller { @@ -66,29 +67,32 @@ public function show(Order $order) public function update(Request $request, Order $order) { // Validasi dokumen jika ada - if ($request->hasFile('document')) { + if ($request->hasFile('lampiran')) { + // unset all validated data + $this->validate = []; $this->validate = [ - 'document' => 'required|mimes:pdf', + 'lampiran' => 'required|mimes:pdf', ]; } // Validasi data yang diterima $validatedData = $request->validate($this->validate); - // Cek dan hapus dokumen lama jika ada - if ($order->document) { - // Hapus dokumen lama dari storage - Storage::disk('public')->delete($order->document); + // Validasi dokumen jika ada + if ($request->hasFile('lampiran')) { + $this->validate['lampiran'] = 'required|mimes:pdf'; + $filePath = $request->file('lampiran')->store('lampiran', 'public'); + $validatedData['lampiran'] = $filePath; } - // Menyimpan dokumen baru jika ada - if ($request->hasFile('document')) { - $filePath = $request->file('document')->store('documents', 'public'); - $validatedData['document'] = $filePath; // Simpan path file ke validated data + // Cek dan hapus dokumen lama jika ada + if ($order->lampiran) { + Storage::disk('public')->delete($order->lampiran); } // Update order dengan data yang sudah divalidasi $order->update($validatedData); + return response()->json($order); } diff --git a/app/Models/Order.php b/app/Models/Order.php index 9350a69..8e22c22 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -16,7 +16,8 @@ class Order extends Model 'price', 'payment_method', 'paid', - 'document' + 'document', + 'lampiran', ]; protected $casts = [ diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php index f5e4ba8..cefdc89 100644 --- a/database/migrations/2024_11_06_033508_create_orders_table.php +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -20,6 +20,7 @@ public function up(): void $table->string('payment_method')->nullable(); $table->integer('paid')->nullable(); $table->text('document')->nullable(); + $table->text('lampiran')->nullable(); $table->timestamps(); }); } From 1cdd6586d02441b2fb45dbc1f510f827e53c44e5 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 20 Dec 2024 15:25:05 +0700 Subject: [PATCH 048/184] tambah condition order --- app/Http/Controllers/OrderController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index ce3a96c..f1fc2bb 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -24,7 +24,7 @@ public function index(Request $request) $customerId = $request->query('customer_id'); $name = $request->query('name'); $status = $request->query('status'); - $status = ($status === 'Arsip') ? 'Selesai' : $status; + $status = isset($status) ? $status : null; // Mulai query dasar $query = Order::with('customer', 'jobdesks'); @@ -43,8 +43,14 @@ public function index(Request $request) if ($status) { $query->whereDoesntHave('jobdesks', function ($query) use ($status) { - $query->where('status', '!=', $status); + $query->where('status', '!=', 'Selesai'); }); + if ($status === 'Selesai') { + $query->whereNotNull('lampiran'); + } + if ($status === 'Arsip') { + $query->whereNull('lampiran'); + } $query->whereHas('jobdesks'); } else { $query->whereHas('jobdesks', function ($query) { From 8d875cf8498b56d2e2ddb5bf4b0490f7a29d7605 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 23 Dec 2024 16:16:01 +0700 Subject: [PATCH 049/184] jobdesk --- app/Http/Controllers/JobdeskController.php | 8 +++++++- database/seeders/DatabaseSeeder.php | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index ae40a0d..b224601 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -11,7 +11,8 @@ public function index(Request $request) { $orderId = $request->query('order_id'); $status = $request->query('status'); - $name = $request->query('name'); // New parameter for employee name + $name = $request->query('name'); + $user_id = $request->query('user_id'); // Initialize the query $query = Jobdesk::with('customer', 'order', 'user'); @@ -26,6 +27,11 @@ public function index(Request $request) $query->where('status', $status); } + // Filter by user_id if provided + if ($user_id) { + $query->where('user_id', $user_id); + } + if ($name && strlen($name) > 2) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index f38f0cd..8bd4a4c 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -38,6 +38,26 @@ public function run(): void 'position' => 'Manager', 'password' => Hash::make('password'), ]); + User::factory()->create([ + 'name' => 'Test Keuangan', + 'email' => 'keuangan@larapi.test', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Keuangan', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test ', + 'email' => 'staff@larapi.test', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Staff', + 'password' => Hash::make('password'), + ]); // Membuat 30 pengguna User::factory(25)->create(); From c4e0a1fba1beec90e10da6f2e56a373354553d4c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 26 Dec 2024 21:02:17 +0700 Subject: [PATCH 050/184] fix migration in server --- .../0001_01_01_000000_create_users_table.php | 10 +++++----- .../0001_01_01_000001_create_cache_table.php | 8 ++++---- .../migrations/0001_01_01_000002_create_jobs_table.php | 4 ++-- ...0_31_042843_create_personal_access_tokens_table.php | 2 +- .../2024_12_17_145546_create_notifications_table.php | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index d0f722b..aea0992 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -27,18 +27,18 @@ public function up(): void }); Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); + $table->string('email', 191)->primary(); // Use VARCHAR(191) + $table->text('token'); $table->timestamp('created_at')->nullable(); }); Schema::create('sessions', function (Blueprint $table) { - $table->string('id')->primary(); - $table->foreignId('user_id')->nullable()->index(); + $table->string('id', 191)->primary(); // Use VARCHAR(191) + $table->unsignedBigInteger('user_id')->nullable(); $table->string('ip_address', 45)->nullable(); $table->text('user_agent')->nullable(); $table->longText('payload'); - $table->integer('last_activity')->index(); + $table->integer('last_activity'); }); } diff --git a/database/migrations/0001_01_01_000001_create_cache_table.php b/database/migrations/0001_01_01_000001_create_cache_table.php index b9c106b..d6ce316 100644 --- a/database/migrations/0001_01_01_000001_create_cache_table.php +++ b/database/migrations/0001_01_01_000001_create_cache_table.php @@ -12,13 +12,13 @@ public function up(): void { Schema::create('cache', function (Blueprint $table) { - $table->string('key')->primary(); - $table->mediumText('value'); - $table->integer('expiration'); + $table->string('key', 191)->primary(); // Use VARCHAR(191) + $table->mediumText('value'); // Keep as mediumText + $table->integer('expiration'); // Keep as is }); Schema::create('cache_locks', function (Blueprint $table) { - $table->string('key')->primary(); + $table->string('key',191)->primary(); $table->string('owner'); $table->integer('expiration'); }); diff --git a/database/migrations/0001_01_01_000002_create_jobs_table.php b/database/migrations/0001_01_01_000002_create_jobs_table.php index 425e705..94efe45 100644 --- a/database/migrations/0001_01_01_000002_create_jobs_table.php +++ b/database/migrations/0001_01_01_000002_create_jobs_table.php @@ -22,8 +22,8 @@ public function up(): void }); Schema::create('job_batches', function (Blueprint $table) { - $table->string('id')->primary(); - $table->string('name'); + $table->string('id', 191)->primary(); + $table->string('name', 255); $table->integer('total_jobs'); $table->integer('pending_jobs'); $table->integer('failed_jobs'); diff --git a/database/migrations/2024_10_31_042843_create_personal_access_tokens_table.php b/database/migrations/2024_10_31_042843_create_personal_access_tokens_table.php index e828ad8..0ffea38 100644 --- a/database/migrations/2024_10_31_042843_create_personal_access_tokens_table.php +++ b/database/migrations/2024_10_31_042843_create_personal_access_tokens_table.php @@ -13,7 +13,7 @@ public function up(): void { Schema::create('personal_access_tokens', function (Blueprint $table) { $table->id(); - $table->morphs('tokenable'); + $table->string('tokenable_type', 191); // Set length for tokenable_type $table->string('name'); $table->string('token', 64)->unique(); $table->text('abilities')->nullable(); diff --git a/database/migrations/2024_12_17_145546_create_notifications_table.php b/database/migrations/2024_12_17_145546_create_notifications_table.php index d738032..002c80d 100644 --- a/database/migrations/2024_12_17_145546_create_notifications_table.php +++ b/database/migrations/2024_12_17_145546_create_notifications_table.php @@ -14,7 +14,7 @@ public function up(): void Schema::create('notifications', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('type'); - $table->morphs('notifiable'); + $table->string('notifiable_type', 191); // Set length for notifiable_type $table->text('data'); $table->timestamp('read_at')->nullable(); $table->timestamps(); From 2827d9c487327a7fe12dd011a92cb6b8a0210acf Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 30 Dec 2024 12:53:00 +0700 Subject: [PATCH 051/184] delete jobdesk by customer --- app/Http/Controllers/CustomerController.php | 2 +- app/Http/Controllers/JobdeskController.php | 7 +++++++ config/cors.php | 4 ++-- larapi | Bin 200704 -> 0 bytes routes/api.php | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 larapi diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index cbf9ddd..f6d5892 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -90,7 +90,7 @@ public function update(Request $request, Customer $customer) public function destroy(Customer $customer) { $customer = Customer::find($customer->id); - // saat hapus customer harus hapus semua order nya + $customer->orders()->jobdesks()->delete(); $customer->orders()->delete(); $customer->delete(); return response()->json($customer); diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index b224601..7a16fb2 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -89,4 +89,11 @@ public function show(Jobdesk $jobdesk) $jobdesk = Jobdesk::find($jobdesk->id)->load('customer', 'order', 'user'); return response()->json($jobdesk); } + + public function destroy(Jobdesk $jobdesk) + { + $jobdesk = Jobdesk::find($jobdesk->id); + $jobdesk->delete(); + return response()->json(['message' => 'Jobdesk deleted successfully']); + } } diff --git a/config/cors.php b/config/cors.php index f2bf88b..771009d 100644 --- a/config/cors.php +++ b/config/cors.php @@ -15,11 +15,11 @@ | */ - 'paths' => ['*'], + 'paths' => ['api/*', 'sanctum/csrf-cookie', ['*']], 'allowed_methods' => ['*'], - 'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], + 'allowed_origins' => ['app.asistennotaris.com'], 'allowed_origins_patterns' => [], diff --git a/larapi b/larapi deleted file mode 100644 index 3117c62f2ed380cbecd71e7c9d4de67b4444dfa6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 200704 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 VB2DKQ{zqQ KaryawanController::class, 'orders' => OrderController::class, From 7da1180b82445ccbf21e1c8777938657141f3335 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 30 Dec 2024 15:08:12 +0700 Subject: [PATCH 052/184] public sementara --- config/cors.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/cors.php b/config/cors.php index 771009d..5182f04 100644 --- a/config/cors.php +++ b/config/cors.php @@ -15,11 +15,11 @@ | */ - 'paths' => ['api/*', 'sanctum/csrf-cookie', ['*']], + 'paths' => ['api/*', 'sanctum/csrf-cookie', '*'], 'allowed_methods' => ['*'], - 'allowed_origins' => ['app.asistennotaris.com'], + 'allowed_origins' => ['*'], 'allowed_origins_patterns' => [], From 23737b4705cd0c53dbde5327e7882717fa7dc365 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 31 Dec 2024 08:43:02 +0700 Subject: [PATCH 053/184] convert is admin to string --- .gitignore | 1 + app/Http/Controllers/UserController.php | 42 +++++++++++++++++++++++++ routes/api.php | 8 +++-- 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/UserController.php diff --git a/.gitignore b/.gitignore index c3ea31b..fc2b090 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ Homestead.yaml auth.json npm-debug.log yarn-error.log +vscode /.fleet /.idea /.vscode diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php new file mode 100644 index 0000000..803519a --- /dev/null +++ b/app/Http/Controllers/UserController.php @@ -0,0 +1,42 @@ +user(); + // { + // "id": 1, + // "name": "Test Admin", + // "email": "test@larapi.test", + // "email_verified_at": "2024-12-23T03:36:38.000000Z", + // "is_admin": 1, + // "avatar": "avatars\/6uC5HtnW5Y441nSkj4nueilglVcbmYYNRBlcaJLA.jpg", + // "phone": "08123456789", + // "address": "Jl. Kebon Jeruk No. 1", + // "position": "Manager", + // "created_at": "2024-12-23T03:36:38.000000Z", + // "updated_at": "2024-12-26T03:47:16.000000Z" + // } + $data = [ + 'id' => $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'email_verified_at' => $user->email_verified_at, + 'is_admin' => strval($user->is_admin), + 'avatar' => $user->avatar, + 'phone' => $user->phone, + 'address' => $user->address, + 'position' => $user->position, + 'created_at' => $user->created_at, + 'updated_at' => $user->updated_at + ]; + return response()->json($data); + } +} diff --git a/routes/api.php b/routes/api.php index f727b8a..52e0ca6 100644 --- a/routes/api.php +++ b/routes/api.php @@ -8,16 +8,18 @@ use App\Http\Controllers\CustomerController; use App\Http\Controllers\DashboardController; use App\Http\Controllers\SettingController; +use App\Http\Controllers\UserController; use App\Http\Controllers\Auth\ProfileController; -Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { - return $request->user(); -}); +// Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { +// return $request->user(); +// }); Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { return $request->user(); }); + Route::get('user', [UserController::class, 'index']); Route::post('jobdesk-reminder', [KaryawanController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('home', [DashboardController::class, 'index']); From 7c2b9c7e8bfa8b3caf5652532e0df0b9622a8d1b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 31 Dec 2024 09:06:11 +0700 Subject: [PATCH 054/184] fix karyawan store --- app/Http/Controllers/KaryawanController.php | 29 +++++++++++++++++++++ app/Http/Controllers/UserController.php | 13 --------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 20fc949..5028caa 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -88,6 +88,35 @@ public function update(Request $request, $id) ], 200); } + public function store(Request $request) + { + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'email' => 'required|email|max:255|unique:users,email', + 'phone' => 'required|string', + 'address' => 'required|string', + 'position' => 'nullable|string', + 'password' => 'required|string|min:8|confirmed', + 'avatar' => 'nullable', + ]); + + // Abaikan 'avatar' jika merupakan string, hanya lanjutkan jika file + if (is_string($request->avatar)) { + unset($validated['avatar']); + } elseif ($request->hasFile('avatar')) { + $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); + } + + $validated['password'] = bcrypt($validated['password']); + $user = User::create($validated); + + return response()->json([ + 'user' => $user, + 'message' => 'Data tersimpan', + 'success' => true + ], 200); + } + public function sendJobdeskReminder(Request $request) { $request->validate([ diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 803519a..7ba70f4 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -11,19 +11,6 @@ public function index(Request $request) { // mengembalikan data user berdasarkan $request / user yang sedang login $user = $request->user(); - // { - // "id": 1, - // "name": "Test Admin", - // "email": "test@larapi.test", - // "email_verified_at": "2024-12-23T03:36:38.000000Z", - // "is_admin": 1, - // "avatar": "avatars\/6uC5HtnW5Y441nSkj4nueilglVcbmYYNRBlcaJLA.jpg", - // "phone": "08123456789", - // "address": "Jl. Kebon Jeruk No. 1", - // "position": "Manager", - // "created_at": "2024-12-23T03:36:38.000000Z", - // "updated_at": "2024-12-26T03:47:16.000000Z" - // } $data = [ 'id' => $user->id, 'name' => $user->name, From 7164852d43a4b8afb66883bd762a23590a0c977f Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 31 Dec 2024 10:12:29 +0700 Subject: [PATCH 055/184] fix filter karyawan --- app/Http/Controllers/KaryawanController.php | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 5028caa..ce6f78c 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -17,12 +17,21 @@ class KaryawanController extends Controller public function index(Request $request) { $page = $request->query('page'); - if ($page === 'all') { - $user = User::all(); - } else { - $user = User::paginate(25); + $name = $request->query('name'); + + // Query dasar semua user + $query = User::query(); + + // Filter berdasarkan name jika ada + if ($name && strlen($name) > 2) { + $query->where('name', 'like', '%' . $name . '%'); } - return response()->json($user); + // shorting descending + $query->orderBy('created_at', 'desc'); + + // Paginate the results + $users = $query->paginate(25); + return response()->json($users); } public function show($id) From 103581a01af70596eb10c4f3a903b13c0a1ae205 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 2 Jan 2025 15:30:56 +0700 Subject: [PATCH 056/184] update setting seeder --- app/Http/Controllers/SettingController.php | 4 ++++ ...024_12_14_102650_create_settings_table.php | 4 ++-- database/seeders/DatabaseSeeder.php | 22 ++++++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index a0cfd85..b54a043 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -30,6 +30,8 @@ public function store(Request $request) 'app_name' => 'nullable|string|max:255', 'app_description' => 'nullable|string|max:500', 'alamat' => 'nullable|string|max:255', + 'banks' => 'nullable|string|max:2000', + 'pekerjaan' => 'nullable|string|max:2000', 'pdf_sample' => 'nullable', 'email' => 'nullable|email|max:255', ]); @@ -90,6 +92,8 @@ public function update(Request $request, $key) 'app_name' => 'nullable|string|max:255', 'app_description' => 'nullable|string|max:500', 'alamat' => 'nullable|string|max:255', + 'banks' => 'nullable|string|max:2000', + 'pekerjaan' => 'nullable|string|max:2000', 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', 'email' => 'nullable|email|max:255', ]); diff --git a/database/migrations/2024_12_14_102650_create_settings_table.php b/database/migrations/2024_12_14_102650_create_settings_table.php index f65cea4..b45b583 100644 --- a/database/migrations/2024_12_14_102650_create_settings_table.php +++ b/database/migrations/2024_12_14_102650_create_settings_table.php @@ -13,8 +13,8 @@ public function up(): void { Schema::create('settings', function (Blueprint $table) { $table->id(); - $table->string('setting_key')->unique(); // Unique key for the setting - $table->text('setting_value')->nullable(); // Value of the setting + $table->string('setting_key')->unique(); + $table->text('setting_value')->nullable(); $table->timestamps(); }); } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 8bd4a4c..27c3087 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -79,11 +79,31 @@ public function run(): void ]); } } - + // { name: 'SKMHT' }, + // { name: 'APHT'}, + // { name: 'Fidusia' }, + // { name: 'Jual beli' }, + // { name: 'Hibah' }, + // { name: 'Turun waris' }, + // { name: 'Aphb' }, + // { name: 'Pendirian PT' }, + // { name: 'Pendirian CV' }, + // { name: 'Pendirian yayasan' }, + // { name: 'Pendirian PT perorangan' }, + // { name: 'Pendirian akta cabang' }, + // { name: 'Perubahan PT' }, + // { name: 'Perub CV' }, + // { name: 'Perub Yayasan' }, + // { name: 'Pecah sertifikat' }, + // { name: 'Pengeringan' }, + // { name: 'PBG' }, + // { name: 'Peningkatan Hak' }, Setting::create(['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT']); Setting::create(['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online']); Setting::create(['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur']); Setting::create(['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf']); Setting::create(['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com']); + Setting::create(['setting_key' => 'banks', 'setting_value' => 'BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat']); + Setting::create(['setting_key' => 'pekerjaan', 'setting_value' => 'SKMHT, APHT, Fidusia, Jual beli, Hibah, Turun waris, Aphb, Pendirian PT, Pendirian CV, Pendirian yayasan, Pendirian PT perorangan, Pendirian akta cabang, Perubahan PT, Perub CV, Perub Yayasan, Pecah sertifikat, Pengeringan, PBG, Peningkatan Hak']); } } From c491ab83d7023b9ac0f4dd0caa4bcc4d97395fb7 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 3 Jan 2025 14:24:52 +0700 Subject: [PATCH 057/184] get setting by key --- app/Http/Controllers/SettingController.php | 14 ++++++++++++-- routes/api.php | 4 ---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index b54a043..09c0958 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -14,9 +14,19 @@ class SettingController extends Controller /** * Display the settings. */ - public function index() + public function index(request $request) { - $settings = Setting::all(); // Retrieve all settings + $setting_key = $request->get('setting_key'); + $query = Setting::query(); + + if ($setting_key) { + $query->where('setting_key', $setting_key); + } else { + $query->orderBy('setting_key', 'asc'); + } + + $settings = $query->get(); + return response()->json($settings); } diff --git a/routes/api.php b/routes/api.php index 52e0ca6..105f658 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,10 +11,6 @@ use App\Http\Controllers\UserController; use App\Http\Controllers\Auth\ProfileController; -// Route::middleware(['auth:sanctum'])->get('/user', function (Request $request) { -// return $request->user(); -// }); - Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { return $request->user(); From 90761961a0dd19c0b4a08c9ea9b3cb4981da7217 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 7 Jan 2025 20:59:19 +0700 Subject: [PATCH 058/184] delete some customer field --- app/Http/Controllers/CustomerController.php | 9 - app/Models/Customer.php | 13 - composer.lock | 2084 ++++++----------- database/factories/CustomerFactory.php | 39 +- ...24_11_01_021016_create_customers_table.php | 9 - 5 files changed, 695 insertions(+), 1459 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index f6d5892..b1cf64f 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -15,15 +15,6 @@ class CustomerController extends Controller 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20', 'alamat' => 'required|string', - 'bank' => 'max:255', - 'kategori' => 'required|string', - 'pekerjaan' => 'max:255', - 'sertifikat' => 'required|string', - 'nilai_transaksi' => 'required|numeric', - 'harga_real' => 'required|numeric', - 'harga_kesepakatan' => 'required|numeric', - 'data_pajak_pembeli' => 'required|numeric', - 'data_pajak_penjual' => 'required|numeric', ]; public function index(Request $request) diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 41df55a..1d0cf82 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -13,19 +13,6 @@ class Customer extends Model 'name', 'phone', 'alamat', - 'kategori', - 'bank', - 'pekerjaan', - 'sertifikat', - 'nilai_transaksi', - 'harga_real', - 'harga_kesepakatan', - 'data_pajak_pembeli', - 'data_pajak_penjual', - ]; - - protected $casts = [ - 'pekerjaan' => 'array', ]; public function orders() diff --git a/composer.lock b/composer.lock index 0a39f96..8f993e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "f72e284aec6964ba6a65b4571522b0b7", + "content-hash": "785aaa5464fc438ca2615f92095171f0", "packages": [ { "name": "brick/math", @@ -445,16 +445,16 @@ }, { "name": "egulias/email-validator", - "version": "4.0.2", + "version": "4.0.3", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e" + "reference": "b115554301161fa21467629f1e1391c1936de517" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/ebaaf5be6c0286928352e054f2d5125608e5405e", - "reference": "ebaaf5be6c0286928352e054f2d5125608e5405e", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b115554301161fa21467629f1e1391c1936de517", + "reference": "b115554301161fa21467629f1e1391c1936de517", "shasum": "" }, "require": { @@ -500,7 +500,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/4.0.2" + "source": "https://github.com/egulias/EmailValidator/tree/4.0.3" }, "funding": [ { @@ -508,7 +508,7 @@ "type": "github" } ], - "time": "2023-10-06T06:47:41+00:00" + "time": "2024-12-27T00:36:43+00:00" }, { "name": "fruitcake/php-cors", @@ -1056,23 +1056,23 @@ }, { "name": "laravel/framework", - "version": "v11.30.0", + "version": "v11.36.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "dff716442d9c229d716be82ccc9a7de52eb97193" + "reference": "df06f5163f4550641fdf349ebc04916a61135a64" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/dff716442d9c229d716be82ccc9a7de52eb97193", - "reference": "dff716442d9c229d716be82ccc9a7de52eb97193", + "url": "https://api.github.com/repos/laravel/framework/zipball/df06f5163f4550641fdf349ebc04916a61135a64", + "reference": "df06f5163f4550641fdf349ebc04916a61135a64", "shasum": "" }, "require": { "brick/math": "^0.9.3|^0.10.2|^0.11|^0.12", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", - "dragonmantank/cron-expression": "^3.3.2", + "dragonmantank/cron-expression": "^3.4", "egulias/email-validator": "^3.2.1|^4.0", "ext-ctype": "*", "ext-filter": "*", @@ -1082,35 +1082,37 @@ "ext-session": "*", "ext-tokenizer": "*", "fruitcake/php-cors": "^1.3", - "guzzlehttp/guzzle": "^7.8", + "guzzlehttp/guzzle": "^7.8.2", "guzzlehttp/uri-template": "^1.0", "laravel/prompts": "^0.1.18|^0.2.0|^0.3.0", - "laravel/serializable-closure": "^1.3", - "league/commonmark": "^2.2.1", - "league/flysystem": "^3.8.0", + "laravel/serializable-closure": "^1.3|^2.0", + "league/commonmark": "^2.6", + "league/flysystem": "^3.25.1", + "league/flysystem-local": "^3.25.1", + "league/uri": "^7.5.1", "monolog/monolog": "^3.0", - "nesbot/carbon": "^2.72.2|^3.0", + "nesbot/carbon": "^2.72.2|^3.4", "nunomaduro/termwind": "^2.0", "php": "^8.2", "psr/container": "^1.1.1|^2.0.1", "psr/log": "^1.0|^2.0|^3.0", "psr/simple-cache": "^1.0|^2.0|^3.0", "ramsey/uuid": "^4.7", - "symfony/console": "^7.0", - "symfony/error-handler": "^7.0", - "symfony/finder": "^7.0", - "symfony/http-foundation": "^7.0", - "symfony/http-kernel": "^7.0", - "symfony/mailer": "^7.0", - "symfony/mime": "^7.0", - "symfony/polyfill-php83": "^1.28", - "symfony/process": "^7.0", - "symfony/routing": "^7.0", - "symfony/uid": "^7.0", - "symfony/var-dumper": "^7.0", + "symfony/console": "^7.0.3", + "symfony/error-handler": "^7.0.3", + "symfony/finder": "^7.0.3", + "symfony/http-foundation": "^7.2.0", + "symfony/http-kernel": "^7.0.3", + "symfony/mailer": "^7.0.3", + "symfony/mime": "^7.0.3", + "symfony/polyfill-php83": "^1.31", + "symfony/process": "^7.0.3", + "symfony/routing": "^7.0.3", + "symfony/uid": "^7.0.3", + "symfony/var-dumper": "^7.0.3", "tijsverkoyen/css-to-inline-styles": "^2.2.5", - "vlucas/phpdotenv": "^5.4.1", - "voku/portable-ascii": "^2.0" + "vlucas/phpdotenv": "^5.6.1", + "voku/portable-ascii": "^2.0.2" }, "conflict": { "mockery/mockery": "1.6.8", @@ -1160,29 +1162,32 @@ }, "require-dev": { "ably/ably-php": "^1.0", - "aws/aws-sdk-php": "^3.235.5", + "aws/aws-sdk-php": "^3.322.9", "ext-gmp": "*", - "fakerphp/faker": "^1.23", - "league/flysystem-aws-s3-v3": "^3.0", - "league/flysystem-ftp": "^3.0", - "league/flysystem-path-prefixing": "^3.3", - "league/flysystem-read-only": "^3.3", - "league/flysystem-sftp-v3": "^3.0", - "mockery/mockery": "^1.6", - "nyholm/psr7": "^1.2", - "orchestra/testbench-core": "^9.5", - "pda/pheanstalk": "^5.0", + "fakerphp/faker": "^1.24", + "guzzlehttp/promises": "^2.0.3", + "guzzlehttp/psr7": "^2.4", + "league/flysystem-aws-s3-v3": "^3.25.1", + "league/flysystem-ftp": "^3.25.1", + "league/flysystem-path-prefixing": "^3.25.1", + "league/flysystem-read-only": "^3.25.1", + "league/flysystem-sftp-v3": "^3.25.1", + "mockery/mockery": "^1.6.10", + "orchestra/testbench-core": "^9.6", + "pda/pheanstalk": "^5.0.6", + "php-http/discovery": "^1.15", "phpstan/phpstan": "^1.11.5", - "phpunit/phpunit": "^10.5|^11.0", - "predis/predis": "^2.0.2", + "phpunit/phpunit": "^10.5.35|^11.3.6", + "predis/predis": "^2.3", "resend/resend-php": "^0.10.0", - "symfony/cache": "^7.0", - "symfony/http-client": "^7.0", - "symfony/psr-http-message-bridge": "^7.0" + "symfony/cache": "^7.0.3", + "symfony/http-client": "^7.0.3", + "symfony/psr-http-message-bridge": "^7.0.3", + "symfony/translation": "^7.0.3" }, "suggest": { "ably/ably-php": "Required to use the Ably broadcast driver (^1.0).", - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.235.5).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage, and SES mail driver (^3.322.9).", "brianium/paratest": "Required to run tests in parallel (^7.0|^8.0).", "ext-apcu": "Required to use the APC cache driver.", "ext-fileinfo": "Required to use the Filesystem class.", @@ -1196,16 +1201,16 @@ "fakerphp/faker": "Required to use the eloquent factory builder (^1.9.1).", "filp/whoops": "Required for friendly error pages in development (^2.14.3).", "laravel/tinker": "Required to use the tinker console command (^2.0).", - "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.0).", - "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.0).", - "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.3).", - "league/flysystem-read-only": "Required to use read-only disks (^3.3)", - "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (^3.25.1).", + "league/flysystem-ftp": "Required to use the Flysystem FTP driver (^3.25.1).", + "league/flysystem-path-prefixing": "Required to use the scoped driver (^3.25.1).", + "league/flysystem-read-only": "Required to use read-only disks (^3.25.1)", + "league/flysystem-sftp-v3": "Required to use the Flysystem SFTP driver (^3.25.1).", "mockery/mockery": "Required to use mocking (^1.6).", - "nyholm/psr7": "Required to use PSR-7 bridging features (^1.2).", "pda/pheanstalk": "Required to use the beanstalk queue driver (^5.0).", + "php-http/discovery": "Required to use PSR-7 bridging features (^1.15).", "phpunit/phpunit": "Required to use assertions and run tests (^10.5|^11.0).", - "predis/predis": "Required to use the predis connector (^2.0.2).", + "predis/predis": "Required to use the predis connector (^2.3).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^6.0|^7.0).", "resend/resend-php": "Required to enable support for the Resend mail transport (^0.10.0).", @@ -1224,6 +1229,7 @@ }, "autoload": { "files": [ + "src/Illuminate/Collections/functions.php", "src/Illuminate/Collections/helpers.php", "src/Illuminate/Events/functions.php", "src/Illuminate/Filesystem/functions.php", @@ -1261,20 +1267,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2024-10-30T15:00:34+00:00" + "time": "2024-12-17T22:32:08+00:00" }, { "name": "laravel/prompts", - "version": "v0.3.1", + "version": "v0.3.2", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "0f3848a445562dac376b27968f753c65e7e1036e" + "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/0f3848a445562dac376b27968f753c65e7e1036e", - "reference": "0f3848a445562dac376b27968f753c65e7e1036e", + "url": "https://api.github.com/repos/laravel/prompts/zipball/0e0535747c6b8d6d10adca8b68293cf4517abb0f", + "reference": "0e0535747c6b8d6d10adca8b68293cf4517abb0f", "shasum": "" }, "require": { @@ -1290,7 +1296,7 @@ "require-dev": { "illuminate/collections": "^10.0|^11.0", "mockery/mockery": "^1.5", - "pestphp/pest": "^2.3", + "pestphp/pest": "^2.3|^3.4", "phpstan/phpstan": "^1.11", "phpstan/phpstan-mockery": "^1.1" }, @@ -1318,22 +1324,22 @@ "description": "Add beautiful and user-friendly forms to your command-line applications.", "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.3.1" + "source": "https://github.com/laravel/prompts/tree/v0.3.2" }, - "time": "2024-10-09T19:42:26+00:00" + "time": "2024-11-12T14:59:47+00:00" }, { "name": "laravel/sanctum", - "version": "v4.0.3", + "version": "v4.0.7", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "54aea9d13743ae8a6cdd3c28dbef128a17adecab" + "reference": "698064236a46df016e64a7eb059b1414e0b281df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/54aea9d13743ae8a6cdd3c28dbef128a17adecab", - "reference": "54aea9d13743ae8a6cdd3c28dbef128a17adecab", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/698064236a46df016e64a7eb059b1414e0b281df", + "reference": "698064236a46df016e64a7eb059b1414e0b281df", "shasum": "" }, "require": { @@ -1384,36 +1390,36 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2024-09-27T14:55:41+00:00" + "time": "2024-12-11T16:40:21+00:00" }, { "name": "laravel/serializable-closure", - "version": "v1.3.5", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/laravel/serializable-closure.git", - "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c" + "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", - "reference": "1dc4a3dbfa2b7628a3114e43e32120cce7cdda9c", + "url": "https://api.github.com/repos/laravel/serializable-closure/zipball/613b2d4998f85564d40497e05e89cb6d9bd1cbe8", + "reference": "613b2d4998f85564d40497e05e89cb6d9bd1cbe8", "shasum": "" }, "require": { - "php": "^7.3|^8.0" + "php": "^8.1" }, "require-dev": { - "illuminate/support": "^8.0|^9.0|^10.0|^11.0", - "nesbot/carbon": "^2.61|^3.0", - "pestphp/pest": "^1.21.3", - "phpstan/phpstan": "^1.8.2", - "symfony/var-dumper": "^5.4.11|^6.2.0|^7.0.0" + "illuminate/support": "^10.0|^11.0", + "nesbot/carbon": "^2.67|^3.0", + "pestphp/pest": "^2.36", + "phpstan/phpstan": "^2.0", + "symfony/var-dumper": "^6.2.0|^7.0.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -1445,7 +1451,7 @@ "issues": "https://github.com/laravel/serializable-closure/issues", "source": "https://github.com/laravel/serializable-closure" }, - "time": "2024-09-23T13:33:08+00:00" + "time": "2024-12-16T15:26:28+00:00" }, { "name": "laravel/tinker", @@ -1515,16 +1521,16 @@ }, { "name": "league/commonmark", - "version": "2.5.3", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0" + "reference": "d990688c91cedfb69753ffc2512727ec646df2ad" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0", - "reference": "b650144166dfa7703e62a22e493b853b58d874b0", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d990688c91cedfb69753ffc2512727ec646df2ad", + "reference": "d990688c91cedfb69753ffc2512727ec646df2ad", "shasum": "" }, "require": { @@ -1549,8 +1555,9 @@ "phpstan/phpstan": "^1.8.2", "phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0", "scrutinizer/ocular": "^1.8.1", - "symfony/finder": "^5.3 | ^6.0 || ^7.0", - "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0", + "symfony/finder": "^5.3 | ^6.0 | ^7.0", + "symfony/process": "^5.4 | ^6.0 | ^7.0", + "symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0", "unleashedtech/php-coding-standard": "^3.1.1", "vimeo/psalm": "^4.24.0 || ^5.0.0" }, @@ -1560,7 +1567,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "2.6-dev" + "dev-main": "2.7-dev" } }, "autoload": { @@ -1617,7 +1624,7 @@ "type": "tidelift" } ], - "time": "2024-08-16T11:46:16+00:00" + "time": "2024-12-29T14:10:59+00:00" }, { "name": "league/config", @@ -1889,18 +1896,192 @@ ], "time": "2024-09-21T08:32:55+00:00" }, + { + "name": "league/uri", + "version": "7.5.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri.git", + "reference": "81fb5145d2644324614cc532b28efd0215bda430" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/81fb5145d2644324614cc532b28efd0215bda430", + "reference": "81fb5145d2644324614cc532b28efd0215bda430", + "shasum": "" + }, + "require": { + "league/uri-interfaces": "^7.5", + "php": "^8.1" + }, + "conflict": { + "league/uri-schemes": "^1.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "URI manipulation library", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "middleware", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "uri-template", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.5.1" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:40:02+00:00" + }, + { + "name": "league/uri-interfaces", + "version": "7.5.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/uri-interfaces.git", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "reference": "08cfc6c4f3d811584fb09c37e2849e6a7f9b0742", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" + }, + "suggest": { + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Uri\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://nyamsprod.com" + } + ], + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", + "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", + "rfc3986", + "rfc3987", + "rfc6570", + "uri", + "url", + "ws" + ], + "support": { + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.5.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/nyamsprod", + "type": "github" + } + ], + "time": "2024-12-08T08:18:47+00:00" + }, { "name": "monolog/monolog", - "version": "3.7.0", + "version": "3.8.1", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8" + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f4393b648b78a5408747de94fca38beb5f7e9ef8", - "reference": "f4393b648b78a5408747de94fca38beb5f7e9ef8", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/aef6ee73a77a66e404dd6540934a9ef1b3c855b4", + "reference": "aef6ee73a77a66e404dd6540934a9ef1b3c855b4", "shasum": "" }, "require": { @@ -1920,12 +2101,14 @@ "guzzlehttp/psr7": "^2.2", "mongodb/mongodb": "^1.8", "php-amqplib/php-amqplib": "~2.4 || ^3", - "phpstan/phpstan": "^1.9", - "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-strict-rules": "^1.4", - "phpunit/phpunit": "^10.5.17", + "php-console/php-console": "^3.1.8", + "phpstan/phpstan": "^2", + "phpstan/phpstan-deprecation-rules": "^2", + "phpstan/phpstan-strict-rules": "^2", + "phpunit/phpunit": "^10.5.17 || ^11.0.7", "predis/predis": "^1.1 || ^2", - "ruflin/elastica": "^7", + "rollbar/rollbar": "^4.0", + "ruflin/elastica": "^7 || ^8", "symfony/mailer": "^5.4 || ^6", "symfony/mime": "^5.4 || ^6" }, @@ -1976,7 +2159,7 @@ ], "support": { "issues": "https://github.com/Seldaek/monolog/issues", - "source": "https://github.com/Seldaek/monolog/tree/3.7.0" + "source": "https://github.com/Seldaek/monolog/tree/3.8.1" }, "funding": [ { @@ -1988,20 +2171,20 @@ "type": "tidelift" } ], - "time": "2024-06-28T09:40:51+00:00" + "time": "2024-12-05T17:15:07+00:00" }, { "name": "nesbot/carbon", - "version": "3.8.1", + "version": "3.8.4", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "10ac0aa86b8062219ce21e8189123d611ca3ecd9" + "reference": "129700ed449b1f02d70272d2ac802357c8c30c58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/10ac0aa86b8062219ce21e8189123d611ca3ecd9", - "reference": "10ac0aa86b8062219ce21e8189123d611ca3ecd9", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/129700ed449b1f02d70272d2ac802357c8c30c58", + "reference": "129700ed449b1f02d70272d2ac802357c8c30c58", "shasum": "" }, "require": { @@ -2033,10 +2216,6 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-master": "3.x-dev", - "dev-2.x": "2.x-dev" - }, "laravel": { "providers": [ "Carbon\\Laravel\\ServiceProvider" @@ -2046,6 +2225,10 @@ "includes": [ "extension.neon" ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" } }, "autoload": { @@ -2094,7 +2277,7 @@ "type": "tidelift" } ], - "time": "2024-11-03T16:02:24+00:00" + "time": "2024-12-27T09:25:35+00:00" }, { "name": "nette/schema", @@ -2246,16 +2429,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.3.1", + "version": "v5.4.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b" + "reference": "447a020a1f875a434d62f2a401f53b82a396e494" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/8eea230464783aa9671db8eea6f8c6ac5285794b", - "reference": "8eea230464783aa9671db8eea6f8c6ac5285794b", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", + "reference": "447a020a1f875a434d62f2a401f53b82a396e494", "shasum": "" }, "require": { @@ -2298,37 +2481,37 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.3.1" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" }, - "time": "2024-10-08T18:51:32+00:00" + "time": "2024-12-30T11:07:19+00:00" }, { "name": "nunomaduro/termwind", - "version": "v2.2.0", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/termwind.git", - "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3" + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/42c84e4e8090766bbd6445d06cd6e57650626ea3", - "reference": "42c84e4e8090766bbd6445d06cd6e57650626ea3", + "url": "https://api.github.com/repos/nunomaduro/termwind/zipball/52915afe6a1044e8b9cee1bcff836fb63acf9cda", + "reference": "52915afe6a1044e8b9cee1bcff836fb63acf9cda", "shasum": "" }, "require": { "ext-mbstring": "*", "php": "^8.2", - "symfony/console": "^7.1.5" + "symfony/console": "^7.1.8" }, "require-dev": { - "illuminate/console": "^11.28.0", - "laravel/pint": "^1.18.1", + "illuminate/console": "^11.33.2", + "laravel/pint": "^1.18.2", "mockery/mockery": "^1.6.12", "pestphp/pest": "^2.36.0", - "phpstan/phpstan": "^1.12.6", + "phpstan/phpstan": "^1.12.11", "phpstan/phpstan-strict-rules": "^1.6.1", - "symfony/var-dumper": "^7.1.5", + "symfony/var-dumper": "^7.1.8", "thecodingmachine/phpstan-strict-rules": "^1.0.0" }, "type": "library", @@ -2371,7 +2554,7 @@ ], "support": { "issues": "https://github.com/nunomaduro/termwind/issues", - "source": "https://github.com/nunomaduro/termwind/tree/v2.2.0" + "source": "https://github.com/nunomaduro/termwind/tree/v2.3.0" }, "funding": [ { @@ -2387,7 +2570,7 @@ "type": "github" } ], - "time": "2024-10-15T16:15:16+00:00" + "time": "2024-11-21T10:39:51+00:00" }, { "name": "phpoption/phpoption", @@ -2878,16 +3061,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.4", + "version": "v0.12.7", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "2fd717afa05341b4f8152547f142cd2f130f6818" + "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/2fd717afa05341b4f8152547f142cd2f130f6818", - "reference": "2fd717afa05341b4f8152547f142cd2f130f6818", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/d73fa3c74918ef4522bb8a3bf9cab39161c4b57c", + "reference": "d73fa3c74918ef4522bb8a3bf9cab39161c4b57c", "shasum": "" }, "require": { @@ -2914,12 +3097,12 @@ ], "type": "library", "extra": { - "branch-alias": { - "dev-main": "0.12.x-dev" - }, "bamarni-bin": { "bin-links": false, "forward-command": false + }, + "branch-alias": { + "dev-main": "0.12.x-dev" } }, "autoload": { @@ -2951,9 +3134,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.4" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.7" }, - "time": "2024-06-10T01:18:23+00:00" + "time": "2024-12-10T01:58:33+00:00" }, { "name": "ralouphie/getallheaders", @@ -3182,16 +3365,16 @@ }, { "name": "symfony/clock", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/clock.git", - "reference": "97bebc53548684c17ed696bc8af016880f0f098d" + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/clock/zipball/97bebc53548684c17ed696bc8af016880f0f098d", - "reference": "97bebc53548684c17ed696bc8af016880f0f098d", + "url": "https://api.github.com/repos/symfony/clock/zipball/b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", + "reference": "b81435fbd6648ea425d1ee96a2d8e68f4ceacd24", "shasum": "" }, "require": { @@ -3236,7 +3419,7 @@ "time" ], "support": { - "source": "https://github.com/symfony/clock/tree/v7.1.6" + "source": "https://github.com/symfony/clock/tree/v7.2.0" }, "funding": [ { @@ -3252,20 +3435,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/console", - "version": "v7.1.6", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "bb5192af6edc797cbab5c8e8ecfea2fe5f421e57" + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/bb5192af6edc797cbab5c8e8ecfea2fe5f421e57", - "reference": "bb5192af6edc797cbab5c8e8ecfea2fe5f421e57", + "url": "https://api.github.com/repos/symfony/console/zipball/fefcc18c0f5d0efe3ab3152f15857298868dc2c3", + "reference": "fefcc18c0f5d0efe3ab3152f15857298868dc2c3", "shasum": "" }, "require": { @@ -3329,7 +3512,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.1.6" + "source": "https://github.com/symfony/console/tree/v7.2.1" }, "funding": [ { @@ -3345,20 +3528,20 @@ "type": "tidelift" } ], - "time": "2024-10-09T08:46:59+00:00" + "time": "2024-12-11T03:49:26+00:00" }, { "name": "symfony/css-selector", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66" + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", - "reference": "4aa4f6b3d6749c14d3aa815eef8226632e7bbc66", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/601a5ce9aaad7bf10797e3663faefce9e26c24e2", + "reference": "601a5ce9aaad7bf10797e3663faefce9e26c24e2", "shasum": "" }, "require": { @@ -3394,7 +3577,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v7.1.6" + "source": "https://github.com/symfony/css-selector/tree/v7.2.0" }, "funding": [ { @@ -3410,20 +3593,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1" + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", - "reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", "shasum": "" }, "require": { @@ -3431,12 +3614,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -3461,7 +3644,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -3477,20 +3660,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/error-handler", - "version": "v7.1.6", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "d60117093c2a9fe667baa8fedf84e8a09b9c592f" + "reference": "6150b89186573046167796fa5f3f76601d5145f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/d60117093c2a9fe667baa8fedf84e8a09b9c592f", - "reference": "d60117093c2a9fe667baa8fedf84e8a09b9c592f", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/6150b89186573046167796fa5f3f76601d5145f8", + "reference": "6150b89186573046167796fa5f3f76601d5145f8", "shasum": "" }, "require": { @@ -3536,7 +3719,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v7.1.6" + "source": "https://github.com/symfony/error-handler/tree/v7.2.1" }, "funding": [ { @@ -3552,20 +3735,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "87254c78dd50721cfd015b62277a8281c5589702" + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/87254c78dd50721cfd015b62277a8281c5589702", - "reference": "87254c78dd50721cfd015b62277a8281c5589702", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/910c5db85a5356d0fea57680defec4e99eb9c8c1", + "reference": "910c5db85a5356d0fea57680defec4e99eb9c8c1", "shasum": "" }, "require": { @@ -3616,7 +3799,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v7.1.6" + "source": "https://github.com/symfony/event-dispatcher/tree/v7.2.0" }, "funding": [ { @@ -3632,20 +3815,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50" + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/8f93aec25d41b72493c6ddff14e916177c9efc50", - "reference": "8f93aec25d41b72493c6ddff14e916177c9efc50", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7642f5e970b672283b7823222ae8ef8bbc160b9f", + "reference": "7642f5e970b672283b7823222ae8ef8bbc160b9f", "shasum": "" }, "require": { @@ -3654,12 +3837,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -3692,7 +3875,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.5.1" }, "funding": [ { @@ -3708,20 +3891,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/finder", - "version": "v7.1.6", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" + "reference": "87a71856f2f56e4100373e92529eed3171695cfb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", - "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", + "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", + "reference": "87a71856f2f56e4100373e92529eed3171695cfb", "shasum": "" }, "require": { @@ -3756,7 +3939,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.6" + "source": "https://github.com/symfony/finder/tree/v7.2.2" }, "funding": [ { @@ -3772,35 +3955,36 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/http-foundation", - "version": "v7.1.6", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "3d7bbf071b25f802f7d55524d408bed414ea71e2" + "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/3d7bbf071b25f802f7d55524d408bed414ea71e2", - "reference": "3d7bbf071b25f802f7d55524d408bed414ea71e2", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/62d1a43796ca3fea3f83a8470dfe63a4af3bc588", + "reference": "62d1a43796ca3fea3f83a8470dfe63a4af3bc588", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-mbstring": "~1.1", "symfony/polyfill-php83": "^1.27" }, "conflict": { "doctrine/dbal": "<3.6", - "symfony/cache": "<6.4" + "symfony/cache": "<6.4.12|>=7.0,<7.1.5" }, "require-dev": { "doctrine/dbal": "^3.6|^4", "predis/predis": "^1.1|^2.0", - "symfony/cache": "^6.4|^7.0", + "symfony/cache": "^6.4.12|^7.1.5", "symfony/dependency-injection": "^6.4|^7.0", "symfony/expression-language": "^6.4|^7.0", "symfony/http-kernel": "^6.4|^7.0", @@ -3833,7 +4017,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v7.1.6" + "source": "https://github.com/symfony/http-foundation/tree/v7.2.2" }, "funding": [ { @@ -3849,20 +4033,20 @@ "type": "tidelift" } ], - "time": "2024-10-11T19:23:14+00:00" + "time": "2024-12-30T19:00:17+00:00" }, { "name": "symfony/http-kernel", - "version": "v7.1.6", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "5d8315899cd76b2e7e29179bf5fea103e41bdf03" + "reference": "3c432966bd8c7ec7429663105f5a02d7e75b4306" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/5d8315899cd76b2e7e29179bf5fea103e41bdf03", - "reference": "5d8315899cd76b2e7e29179bf5fea103e41bdf03", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/3c432966bd8c7ec7429663105f5a02d7e75b4306", + "reference": "3c432966bd8c7ec7429663105f5a02d7e75b4306", "shasum": "" }, "require": { @@ -3891,7 +4075,7 @@ "symfony/twig-bridge": "<6.4", "symfony/validator": "<6.4", "symfony/var-dumper": "<6.4", - "twig/twig": "<3.0.4" + "twig/twig": "<3.12" }, "provide": { "psr/log-implementation": "1.0|2.0|3.0" @@ -3919,7 +4103,7 @@ "symfony/validator": "^6.4|^7.0", "symfony/var-dumper": "^6.4|^7.0", "symfony/var-exporter": "^6.4|^7.0", - "twig/twig": "^3.0.4" + "twig/twig": "^3.12" }, "type": "library", "autoload": { @@ -3947,7 +4131,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v7.1.6" + "source": "https://github.com/symfony/http-kernel/tree/v7.2.2" }, "funding": [ { @@ -3963,20 +4147,20 @@ "type": "tidelift" } ], - "time": "2024-10-27T13:54:21+00:00" + "time": "2024-12-31T14:59:40+00:00" }, { "name": "symfony/mailer", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd" + "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/69c9948451fb3a6a4d47dc8261d1794734e76cdd", - "reference": "69c9948451fb3a6a4d47dc8261d1794734e76cdd", + "url": "https://api.github.com/repos/symfony/mailer/zipball/e4d358702fb66e4c8a2af08e90e7271a62de39cc", + "reference": "e4d358702fb66e4c8a2af08e90e7271a62de39cc", "shasum": "" }, "require": { @@ -3985,7 +4169,7 @@ "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^6.4|^7.0", - "symfony/mime": "^6.4|^7.0", + "symfony/mime": "^7.2", "symfony/service-contracts": "^2.5|^3" }, "conflict": { @@ -4027,7 +4211,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v7.1.6" + "source": "https://github.com/symfony/mailer/tree/v7.2.0" }, "funding": [ { @@ -4043,20 +4227,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-25T15:21:05+00:00" }, { "name": "symfony/mime", - "version": "v7.1.6", + "version": "v7.2.1", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "caa1e521edb2650b8470918dfe51708c237f0598" + "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/caa1e521edb2650b8470918dfe51708c237f0598", - "reference": "caa1e521edb2650b8470918dfe51708c237f0598", + "url": "https://api.github.com/repos/symfony/mime/zipball/7f9617fcf15cb61be30f8b252695ed5e2bfac283", + "reference": "7f9617fcf15cb61be30f8b252695ed5e2bfac283", "shasum": "" }, "require": { @@ -4111,7 +4295,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v7.1.6" + "source": "https://github.com/symfony/mime/tree/v7.2.1" }, "funding": [ { @@ -4127,7 +4311,7 @@ "type": "tidelift" } ], - "time": "2024-10-25T15:11:02+00:00" + "time": "2024-12-07T08:50:44+00:00" }, { "name": "symfony/polyfill-ctype", @@ -4155,8 +4339,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4231,8 +4415,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4310,8 +4494,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4392,8 +4576,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4476,8 +4660,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4550,8 +4734,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4630,8 +4814,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4712,8 +4896,8 @@ "type": "library", "extra": { "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" + "url": "https://github.com/symfony/polyfill", + "name": "symfony/polyfill" } }, "autoload": { @@ -4767,16 +4951,16 @@ }, { "name": "symfony/process", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e" + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e", - "reference": "6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e", + "url": "https://api.github.com/repos/symfony/process/zipball/d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", + "reference": "d34b22ba9390ec19d2dd966c40aa9e8462f27a7e", "shasum": "" }, "require": { @@ -4808,7 +4992,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.6" + "source": "https://github.com/symfony/process/tree/v7.2.0" }, "funding": [ { @@ -4824,20 +5008,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-06T14:24:19+00:00" }, { "name": "symfony/routing", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a" + "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/66a2c469f6c22d08603235c46a20007c0701ea0a", - "reference": "66a2c469f6c22d08603235c46a20007c0701ea0a", + "url": "https://api.github.com/repos/symfony/routing/zipball/e10a2450fa957af6c448b9b93c9010a4e4c0725e", + "reference": "e10a2450fa957af6c448b9b93c9010a4e4c0725e", "shasum": "" }, "require": { @@ -4889,7 +5073,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v7.1.6" + "source": "https://github.com/symfony/routing/tree/v7.2.0" }, "funding": [ { @@ -4905,20 +5089,20 @@ "type": "tidelift" } ], - "time": "2024-10-01T08:31:23+00:00" + "time": "2024-11-25T11:08:51+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", - "reference": "bd1d9e59a81d8fa4acdcea3f617c581f7475a80f", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { @@ -4931,12 +5115,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -4972,7 +5156,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -4988,20 +5172,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626" + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/61b72d66bf96c360a727ae6232df5ac83c71f626", - "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626", + "url": "https://api.github.com/repos/symfony/string/zipball/446e0d146f991dde3e73f45f2c97a9faad773c82", + "reference": "446e0d146f991dde3e73f45f2c97a9faad773c82", "shasum": "" }, "require": { @@ -5059,7 +5243,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.6" + "source": "https://github.com/symfony/string/tree/v7.2.0" }, "funding": [ { @@ -5075,24 +5259,25 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-13T13:31:26+00:00" }, { "name": "symfony/translation", - "version": "v7.1.6", + "version": "v7.2.2", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f" + "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/b9f72ab14efdb6b772f85041fa12f820dee8d55f", - "reference": "b9f72ab14efdb6b772f85041fa12f820dee8d55f", + "url": "https://api.github.com/repos/symfony/translation/zipball/e2674a30132b7cc4d74540d6c2573aa363f05923", + "reference": "e2674a30132b7cc4d74540d6c2573aa363f05923", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.5|^3.0" }, @@ -5153,7 +5338,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v7.1.6" + "source": "https://github.com/symfony/translation/tree/v7.2.2" }, "funding": [ { @@ -5169,20 +5354,20 @@ "type": "tidelift" } ], - "time": "2024-09-28T12:35:13+00:00" + "time": "2024-12-07T08:18:10+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.5.0", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a" + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", - "reference": "b9d2189887bb6b2e0367a9fc7136c5239ab9b05a", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/4667ff3bd513750603a09c8dedbea942487fb07c", + "reference": "4667ff3bd513750603a09c8dedbea942487fb07c", "shasum": "" }, "require": { @@ -5190,12 +5375,12 @@ }, "type": "library", "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, "branch-alias": { "dev-main": "3.5-dev" - }, - "thanks": { - "name": "symfony/contracts", - "url": "https://github.com/symfony/contracts" } }, "autoload": { @@ -5231,7 +5416,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.5.0" + "source": "https://github.com/symfony/translation-contracts/tree/v3.5.1" }, "funding": [ { @@ -5247,20 +5432,20 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:32:20+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/uid", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "65befb3bb2d503bbffbd08c815aa38b472999917" + "reference": "2d294d0c48df244c71c105a169d0190bfb080426" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/65befb3bb2d503bbffbd08c815aa38b472999917", - "reference": "65befb3bb2d503bbffbd08c815aa38b472999917", + "url": "https://api.github.com/repos/symfony/uid/zipball/2d294d0c48df244c71c105a169d0190bfb080426", + "reference": "2d294d0c48df244c71c105a169d0190bfb080426", "shasum": "" }, "require": { @@ -5305,7 +5490,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v7.1.6" + "source": "https://github.com/symfony/uid/tree/v7.2.0" }, "funding": [ { @@ -5321,20 +5506,20 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c" + "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c", - "reference": "cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/c6a22929407dec8765d6e2b6ff85b800b245879c", + "reference": "c6a22929407dec8765d6e2b6ff85b800b245879c", "shasum": "" }, "require": { @@ -5350,7 +5535,7 @@ "symfony/http-kernel": "^6.4|^7.0", "symfony/process": "^6.4|^7.0", "symfony/uid": "^6.4|^7.0", - "twig/twig": "^3.0.4" + "twig/twig": "^3.12" }, "bin": [ "Resources/bin/var-dump-server" @@ -5388,7 +5573,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.6" + "source": "https://github.com/symfony/var-dumper/tree/v7.2.0" }, "funding": [ { @@ -5404,35 +5589,37 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-11-08T15:48:14+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "v2.2.7", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb" + "reference": "0d72ac1c00084279c1816675284073c5a337c20d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb", - "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d", + "reference": "0d72ac1c00084279c1816675284073c5a337c20d", "shasum": "" }, "require": { "ext-dom": "*", "ext-libxml": "*", - "php": "^5.5 || ^7.0 || ^8.0", - "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0" + "php": "^7.4 || ^8.0", + "symfony/css-selector": "^5.4 || ^6.0 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10" + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^8.5.21 || ^9.5.10" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.x-dev" } }, "autoload": { @@ -5455,9 +5642,9 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.2.7" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0" }, - "time": "2023-12-08T13:03:43+00:00" + "time": "2024-12-21T16:25:41+00:00" }, { "name": "vlucas/phpdotenv", @@ -5545,16 +5732,16 @@ }, { "name": "voku/portable-ascii", - "version": "2.0.1", + "version": "2.0.3", "source": { "type": "git", "url": "https://github.com/voku/portable-ascii.git", - "reference": "b56450eed252f6801410d810c8e1727224ae0743" + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b56450eed252f6801410d810c8e1727224ae0743", - "reference": "b56450eed252f6801410d810c8e1727224ae0743", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", + "reference": "b1d923f88091c6bf09699efcd7c8a1b1bfd7351d", "shasum": "" }, "require": { @@ -5579,7 +5766,7 @@ "authors": [ { "name": "Lars Moelleken", - "homepage": "http://www.moelleken.org/" + "homepage": "https://www.moelleken.org/" } ], "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", @@ -5591,7 +5778,7 @@ ], "support": { "issues": "https://github.com/voku/portable-ascii/issues", - "source": "https://github.com/voku/portable-ascii/tree/2.0.1" + "source": "https://github.com/voku/portable-ascii/tree/2.0.3" }, "funding": [ { @@ -5615,7 +5802,7 @@ "type": "tidelift" } ], - "time": "2022-03-08T17:03:00+00:00" + "time": "2024-11-21T01:49:47+00:00" }, { "name": "webmozart/assert", @@ -5677,158 +5864,18 @@ } ], "packages-dev": [ - { - "name": "brianium/paratest", - "version": "v7.6.0", - "source": { - "type": "git", - "url": "https://github.com/paratestphp/paratest.git", - "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paratestphp/paratest/zipball/68ff89a8de47d086588e391a516d2a5b5fde6254", - "reference": "68ff89a8de47d086588e391a516d2a5b5fde6254", - "shasum": "" - }, - "require": { - "ext-dom": "*", - "ext-pcre": "*", - "ext-reflection": "*", - "ext-simplexml": "*", - "fidry/cpu-core-counter": "^1.2.0", - "jean85/pretty-package-versions": "^2.0.6", - "php": "~8.2.0 || ~8.3.0 || ~8.4.0", - "phpunit/php-code-coverage": "^11.0.7", - "phpunit/php-file-iterator": "^5.1.0", - "phpunit/php-timer": "^7.0.1", - "phpunit/phpunit": "^11.4.1", - "sebastian/environment": "^7.2.0", - "symfony/console": "^6.4.11 || ^7.1.5", - "symfony/process": "^6.4.8 || ^7.1.5" - }, - "require-dev": { - "doctrine/coding-standard": "^12.0.0", - "ext-pcov": "*", - "ext-posix": "*", - "phpstan/phpstan": "^1.12.6", - "phpstan/phpstan-deprecation-rules": "^1.2.1", - "phpstan/phpstan-phpunit": "^1.4.0", - "phpstan/phpstan-strict-rules": "^1.6.1", - "squizlabs/php_codesniffer": "^3.10.3", - "symfony/filesystem": "^6.4.9 || ^7.1.5" - }, - "bin": [ - "bin/paratest", - "bin/paratest_for_phpstorm" - ], - "type": "library", - "autoload": { - "psr-4": { - "ParaTest\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Brian Scaturro", - "email": "scaturrob@gmail.com", - "role": "Developer" - }, - { - "name": "Filippo Tessarotto", - "email": "zoeslam@gmail.com", - "role": "Developer" - } - ], - "description": "Parallel testing for PHP", - "homepage": "https://github.com/paratestphp/paratest", - "keywords": [ - "concurrent", - "parallel", - "phpunit", - "testing" - ], - "support": { - "issues": "https://github.com/paratestphp/paratest/issues", - "source": "https://github.com/paratestphp/paratest/tree/v7.6.0" - }, - "funding": [ - { - "url": "https://github.com/sponsors/Slamdunk", - "type": "github" - }, - { - "url": "https://paypal.me/filippotessarotto", - "type": "paypal" - } - ], - "time": "2024-10-15T12:38:31+00:00" - }, - { - "name": "doctrine/deprecations", - "version": "1.1.3", - "source": { - "type": "git", - "url": "https://github.com/doctrine/deprecations.git", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/deprecations/zipball/dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "reference": "dfbaa3c2d2e9a9df1118213f3b8b0c597bb99fab", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9", - "phpstan/phpstan": "1.4.10 || 1.10.15", - "phpstan/phpstan-phpunit": "^1.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "psalm/plugin-phpunit": "0.18.4", - "psr/log": "^1 || ^2 || ^3", - "vimeo/psalm": "4.30.0 || 5.12.0" - }, - "suggest": { - "psr/log": "Allows logging deprecations via PSR-3 logger implementation" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", - "homepage": "https://www.doctrine-project.org/", - "support": { - "issues": "https://github.com/doctrine/deprecations/issues", - "source": "https://github.com/doctrine/deprecations/tree/1.1.3" - }, - "time": "2024-01-30T19:34:25+00:00" - }, { "name": "fakerphp/faker", - "version": "v1.23.1", + "version": "v1.24.1", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b" + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b", - "reference": "bfb4fe148adbf78eff521199619b93a52ae3554b", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", + "reference": "e0ee18eb1e6dc3cda3ce9fd97e5a0689a88a64b5", "shasum": "" }, "require": { @@ -5876,42 +5923,46 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.23.1" + "source": "https://github.com/FakerPHP/Faker/tree/v1.24.1" }, - "time": "2024-01-02T13:46:09+00:00" + "time": "2024-11-21T13:46:39+00:00" }, { - "name": "fidry/cpu-core-counter", - "version": "1.2.0", + "name": "filp/whoops", + "version": "2.16.0", "source": { "type": "git", - "url": "https://github.com/theofidry/cpu-core-counter.git", - "reference": "8520451a140d3f46ac33042715115e290cf5785f" + "url": "https://github.com/filp/whoops.git", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/theofidry/cpu-core-counter/zipball/8520451a140d3f46ac33042715115e290cf5785f", - "reference": "8520451a140d3f46ac33042715115e290cf5785f", + "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", + "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", "shasum": "" }, "require": { - "php": "^7.2 || ^8.0" + "php": "^7.1 || ^8.0", + "psr/log": "^1.0.1 || ^2.0 || ^3.0" }, "require-dev": { - "fidry/makefile": "^0.2.0", - "fidry/php-cs-fixer-config": "^1.1.2", - "phpstan/extension-installer": "^1.2.0", - "phpstan/phpstan": "^1.9.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", - "phpstan/phpstan-phpunit": "^1.2.2", - "phpstan/phpstan-strict-rules": "^1.4.4", - "phpunit/phpunit": "^8.5.31 || ^9.5.26", - "webmozarts/strict-phpunit": "^7.5" + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", + "symfony/var-dumper": "^4.0 || ^5.0" + }, + "suggest": { + "symfony/var-dumper": "Pretty print complex values better with var-dumper available", + "whoops/soap": "Formats errors as SOAP responses" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, "autoload": { "psr-4": { - "Fidry\\CpuCoreCounter\\": "src/" + "Whoops\\": "src/Whoops/" } }, "notification-url": "https://packagist.org/downloads/", @@ -5920,78 +5971,13 @@ ], "authors": [ { - "name": "Théo FIDRY", - "email": "theo.fidry@gmail.com" + "name": "Filipe Dobreira", + "homepage": "https://github.com/filp", + "role": "Developer" } ], - "description": "Tiny utility to get the number of CPU cores.", - "keywords": [ - "CPU", - "core" - ], - "support": { - "issues": "https://github.com/theofidry/cpu-core-counter/issues", - "source": "https://github.com/theofidry/cpu-core-counter/tree/1.2.0" - }, - "funding": [ - { - "url": "https://github.com/theofidry", - "type": "github" - } - ], - "time": "2024-08-06T10:04:20+00:00" - }, - { - "name": "filp/whoops", - "version": "2.16.0", - "source": { - "type": "git", - "url": "https://github.com/filp/whoops.git", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/befcdc0e5dce67252aa6322d82424be928214fa2", - "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0", - "psr/log": "^1.0.1 || ^2.0 || ^3.0" - }, - "require-dev": { - "mockery/mockery": "^1.0", - "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", - "symfony/var-dumper": "^4.0 || ^5.0" - }, - "suggest": { - "symfony/var-dumper": "Pretty print complex values better with var-dumper available", - "whoops/soap": "Formats errors as SOAP responses" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.7-dev" - } - }, - "autoload": { - "psr-4": { - "Whoops\\": "src/Whoops/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Filipe Dobreira", - "homepage": "https://github.com/filp", - "role": "Developer" - } - ], - "description": "php error handling for cool kids", - "homepage": "https://filp.github.io/whoops/", + "description": "php error handling for cool kids", + "homepage": "https://filp.github.io/whoops/", "keywords": [ "error", "exception", @@ -6063,77 +6049,18 @@ }, "time": "2020-07-09T08:09:16+00:00" }, - { - "name": "jean85/pretty-package-versions", - "version": "2.0.6", - "source": { - "type": "git", - "url": "https://github.com/Jean85/pretty-package-versions.git", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/Jean85/pretty-package-versions/zipball/f9fdd29ad8e6d024f52678b570e5593759b550b4", - "reference": "f9fdd29ad8e6d024f52678b570e5593759b550b4", - "shasum": "" - }, - "require": { - "composer-runtime-api": "^2.0.0", - "php": "^7.1|^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^3.2", - "jean85/composer-provided-replaced-stub-package": "^1.0", - "phpstan/phpstan": "^1.4", - "phpunit/phpunit": "^7.5|^8.5|^9.4", - "vimeo/psalm": "^4.3" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "Jean85\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alessandro Lai", - "email": "alessandro.lai85@gmail.com" - } - ], - "description": "A library to get pretty versions strings of installed dependencies", - "keywords": [ - "composer", - "package", - "release", - "versions" - ], - "support": { - "issues": "https://github.com/Jean85/pretty-package-versions/issues", - "source": "https://github.com/Jean85/pretty-package-versions/tree/2.0.6" - }, - "time": "2024-03-08T09:58:59+00:00" - }, { "name": "laravel/breeze", - "version": "v2.2.4", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/laravel/breeze.git", - "reference": "d3484d08aaaa84896bdd2d1787e7da0fc03f676f" + "reference": "d59702967b9ae21879df905d691a50132966c4ff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/breeze/zipball/d3484d08aaaa84896bdd2d1787e7da0fc03f676f", - "reference": "d3484d08aaaa84896bdd2d1787e7da0fc03f676f", + "url": "https://api.github.com/repos/laravel/breeze/zipball/d59702967b9ae21879df905d691a50132966c4ff", + "reference": "d59702967b9ae21879df905d691a50132966c4ff", "shasum": "" }, "require": { @@ -6145,8 +6072,9 @@ "symfony/console": "^7.0" }, "require-dev": { - "orchestra/testbench": "^9.0", - "phpstan/phpstan": "^1.10" + "laravel/framework": "^11.0", + "orchestra/testbench-core": "^9.0", + "phpstan/phpstan": "^2.0" }, "type": "library", "extra": { @@ -6180,20 +6108,20 @@ "issues": "https://github.com/laravel/breeze/issues", "source": "https://github.com/laravel/breeze" }, - "time": "2024-10-29T15:11:57+00:00" + "time": "2024-12-14T21:21:42+00:00" }, { "name": "laravel/pail", - "version": "v1.2.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/laravel/pail.git", - "reference": "085a2306b520c3896afa361c25704e5fa3c27bf0" + "reference": "353ac12134b98e2e7c3333d916bd3e523931e583" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pail/zipball/085a2306b520c3896afa361c25704e5fa3c27bf0", - "reference": "085a2306b520c3896afa361c25704e5fa3c27bf0", + "url": "https://api.github.com/repos/laravel/pail/zipball/353ac12134b98e2e7c3333d916bd3e523931e583", + "reference": "353ac12134b98e2e7c3333d916bd3e523931e583", "shasum": "" }, "require": { @@ -6208,8 +6136,9 @@ "symfony/console": "^6.0|^7.0" }, "require-dev": { + "laravel/framework": "^10.24|^11.0", "laravel/pint": "^1.13", - "orchestra/testbench": "^8.12|^9.0", + "orchestra/testbench-core": "^8.12|^9.0", "pestphp/pest": "^2.20", "pestphp/pest-plugin-type-coverage": "^2.3", "phpstan/phpstan": "^1.10", @@ -6217,13 +6146,13 @@ }, "type": "library", "extra": { - "branch-alias": { - "dev-main": "1.x-dev" - }, "laravel": { "providers": [ "Laravel\\Pail\\PailServiceProvider" ] + }, + "branch-alias": { + "dev-main": "1.x-dev" } }, "autoload": { @@ -6257,20 +6186,20 @@ "issues": "https://github.com/laravel/pail/issues", "source": "https://github.com/laravel/pail" }, - "time": "2024-10-21T13:59:30+00:00" + "time": "2024-10-23T12:56:23+00:00" }, { "name": "laravel/pint", - "version": "v1.18.1", + "version": "v1.19.0", "source": { "type": "git", "url": "https://github.com/laravel/pint.git", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9" + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pint/zipball/35c00c05ec43e6b46d295efc0f4386ceb30d50d9", - "reference": "35c00c05ec43e6b46d295efc0f4386ceb30d50d9", + "url": "https://api.github.com/repos/laravel/pint/zipball/8169513746e1bac70c85d6ea1524d9225d4886f0", + "reference": "8169513746e1bac70c85d6ea1524d9225d4886f0", "shasum": "" }, "require": { @@ -6281,13 +6210,13 @@ "php": "^8.1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^3.64.0", - "illuminate/view": "^10.48.20", - "larastan/larastan": "^2.9.8", - "laravel-zero/framework": "^10.4.0", + "friendsofphp/php-cs-fixer": "^3.66.0", + "illuminate/view": "^10.48.25", + "larastan/larastan": "^2.9.12", + "laravel-zero/framework": "^10.48.25", "mockery/mockery": "^1.6.12", - "nunomaduro/termwind": "^1.15.1", - "pestphp/pest": "^2.35.1" + "nunomaduro/termwind": "^1.17.0", + "pestphp/pest": "^2.36.0" }, "bin": [ "builds/pint" @@ -6323,20 +6252,20 @@ "issues": "https://github.com/laravel/pint/issues", "source": "https://github.com/laravel/pint" }, - "time": "2024-09-24T17:22:50+00:00" + "time": "2024-12-30T16:20:10+00:00" }, { "name": "laravel/sail", - "version": "v1.37.1", + "version": "v1.39.1", "source": { "type": "git", "url": "https://github.com/laravel/sail.git", - "reference": "7efa151ea0d16f48233d6a6cd69f81270acc6e93" + "reference": "1a3c7291bc88de983b66688919a4d298d68ddec7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sail/zipball/7efa151ea0d16f48233d6a6cd69f81270acc6e93", - "reference": "7efa151ea0d16f48233d6a6cd69f81270acc6e93", + "url": "https://api.github.com/repos/laravel/sail/zipball/1a3c7291bc88de983b66688919a4d298d68ddec7", + "reference": "1a3c7291bc88de983b66688919a4d298d68ddec7", "shasum": "" }, "require": { @@ -6386,7 +6315,7 @@ "issues": "https://github.com/laravel/sail/issues", "source": "https://github.com/laravel/sail" }, - "time": "2024-10-29T20:18:14+00:00" + "time": "2024-11-27T15:42:28+00:00" }, { "name": "mockery/mockery", @@ -6473,16 +6402,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.0", + "version": "1.12.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", - "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", + "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", "shasum": "" }, "require": { @@ -6521,7 +6450,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" }, "funding": [ { @@ -6529,7 +6458,7 @@ "type": "tidelift" } ], - "time": "2024-06-12T14:39:25+00:00" + "time": "2024-11-08T17:47:46+00:00" }, { "name": "nunomaduro/collision", @@ -6567,422 +6496,22 @@ "sebastian/environment": "^6.1.0 || ^7.2.0" }, "type": "library", - "extra": { - "laravel": { - "providers": [ - "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" - ] - }, - "branch-alias": { - "dev-8.x": "8.x-dev" - } - }, - "autoload": { - "files": [ - "./src/Adapters/Phpunit/Autoload.php" - ], - "psr-4": { - "NunoMaduro\\Collision\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" - } - ], - "description": "Cli error handling for console/command-line PHP applications.", - "keywords": [ - "artisan", - "cli", - "command-line", - "console", - "error", - "handling", - "laravel", - "laravel-zero", - "php", - "symfony" - ], - "support": { - "issues": "https://github.com/nunomaduro/collision/issues", - "source": "https://github.com/nunomaduro/collision" - }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2024-10-15T16:06:32+00:00" - }, - { - "name": "pestphp/pest", - "version": "v3.5.1", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest.git", - "reference": "179d46ce97d52bcb3f791449ae94025c3f32e3e3" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest/zipball/179d46ce97d52bcb3f791449ae94025c3f32e3e3", - "reference": "179d46ce97d52bcb3f791449ae94025c3f32e3e3", - "shasum": "" - }, - "require": { - "brianium/paratest": "^7.6.0", - "nunomaduro/collision": "^8.5.0", - "nunomaduro/termwind": "^2.2.0", - "pestphp/pest-plugin": "^3.0.0", - "pestphp/pest-plugin-arch": "^3.0.0", - "pestphp/pest-plugin-mutate": "^3.0.5", - "php": "^8.2.0", - "phpunit/phpunit": "^11.4.3" - }, - "conflict": { - "filp/whoops": "<2.16.0", - "phpunit/phpunit": ">11.4.3", - "sebastian/exporter": "<6.0.0", - "webmozart/assert": "<1.11.0" - }, - "require-dev": { - "pestphp/pest-dev-tools": "^3.3.0", - "pestphp/pest-plugin-type-coverage": "^3.1.0", - "symfony/process": "^7.1.6" - }, - "bin": [ - "bin/pest" - ], - "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pest\\Mutate\\Plugins\\Mutate", - "Pest\\Plugins\\Configuration", - "Pest\\Plugins\\Bail", - "Pest\\Plugins\\Cache", - "Pest\\Plugins\\Coverage", - "Pest\\Plugins\\Init", - "Pest\\Plugins\\Environment", - "Pest\\Plugins\\Help", - "Pest\\Plugins\\Memory", - "Pest\\Plugins\\Only", - "Pest\\Plugins\\Printer", - "Pest\\Plugins\\ProcessIsolation", - "Pest\\Plugins\\Profile", - "Pest\\Plugins\\Retry", - "Pest\\Plugins\\Snapshot", - "Pest\\Plugins\\Verbose", - "Pest\\Plugins\\Version", - "Pest\\Plugins\\Parallel" - ] - }, - "phpstan": { - "includes": [ - "extension.neon" - ] - } - }, - "autoload": { - "files": [ - "src/Functions.php", - "src/Pest.php" - ], - "psr-4": { - "Pest\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" - } - ], - "description": "The elegant PHP Testing Framework.", - "keywords": [ - "framework", - "pest", - "php", - "test", - "testing", - "unit" - ], - "support": { - "issues": "https://github.com/pestphp/pest/issues", - "source": "https://github.com/pestphp/pest/tree/v3.5.1" - }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - } - ], - "time": "2024-10-31T16:12:45+00:00" - }, - { - "name": "pestphp/pest-plugin", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin.git", - "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin/zipball/e79b26c65bc11c41093b10150c1341cc5cdbea83", - "reference": "e79b26c65bc11c41093b10150c1341cc5cdbea83", - "shasum": "" - }, - "require": { - "composer-plugin-api": "^2.0.0", - "composer-runtime-api": "^2.2.2", - "php": "^8.2" - }, - "conflict": { - "pestphp/pest": "<3.0.0" - }, - "require-dev": { - "composer/composer": "^2.7.9", - "pestphp/pest": "^3.0.0", - "pestphp/pest-dev-tools": "^3.0.0" - }, - "type": "composer-plugin", - "extra": { - "class": "Pest\\Plugin\\Manager" - }, - "autoload": { - "psr-4": { - "Pest\\Plugin\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Pest plugin manager", - "keywords": [ - "framework", - "manager", - "pest", - "php", - "plugin", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin/tree/v3.0.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=66BYDWAT92N6L", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - }, - { - "url": "https://www.patreon.com/nunomaduro", - "type": "patreon" - } - ], - "time": "2024-09-08T23:21:41+00:00" - }, - { - "name": "pestphp/pest-plugin-arch", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-arch.git", - "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-arch/zipball/0a27e55a270cfe73d8cb70551b91002ee2cb64b0", - "reference": "0a27e55a270cfe73d8cb70551b91002ee2cb64b0", - "shasum": "" - }, - "require": { - "pestphp/pest-plugin": "^3.0.0", - "php": "^8.2", - "ta-tikoma/phpunit-architecture-test": "^0.8.4" - }, - "require-dev": { - "pestphp/pest": "^3.0.0", - "pestphp/pest-dev-tools": "^3.0.0" - }, - "type": "library", - "extra": { - "pest": { - "plugins": [ - "Pest\\Arch\\Plugin" - ] - } - }, - "autoload": { - "files": [ - "src/Autoload.php" - ], - "psr-4": { - "Pest\\Arch\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Arch plugin for Pest PHP.", - "keywords": [ - "arch", - "architecture", - "framework", - "pest", - "php", - "plugin", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin-arch/tree/v3.0.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - } - ], - "time": "2024-09-08T23:23:55+00:00" - }, - { - "name": "pestphp/pest-plugin-laravel", - "version": "v3.0.0", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-laravel.git", - "reference": "7dd98c0c3b3542970ec21fce80ec5c88916ac469" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-laravel/zipball/7dd98c0c3b3542970ec21fce80ec5c88916ac469", - "reference": "7dd98c0c3b3542970ec21fce80ec5c88916ac469", - "shasum": "" - }, - "require": { - "laravel/framework": "^11.22.0", - "pestphp/pest": "^3.0.0", - "php": "^8.2.0" - }, - "require-dev": { - "laravel/dusk": "^8.2.5", - "orchestra/testbench": "^9.4.0", - "pestphp/pest-dev-tools": "^3.0.0" - }, - "type": "library", - "extra": { - "laravel": { - "providers": [ - "Pest\\Laravel\\PestServiceProvider" - ] - }, - "pest": { - "plugins": [ - "Pest\\Laravel\\Plugin" - ] - } - }, - "autoload": { - "files": [ - "src/Autoload.php" - ], - "psr-4": { - "Pest\\Laravel\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "The Pest Laravel Plugin", - "keywords": [ - "framework", - "laravel", - "pest", - "php", - "test", - "testing", - "unit" - ], - "support": { - "source": "https://github.com/pestphp/pest-plugin-laravel/tree/v3.0.0" - }, - "funding": [ - { - "url": "https://www.paypal.com/paypalme/enunomaduro", - "type": "custom" - }, - { - "url": "https://github.com/nunomaduro", - "type": "github" - } - ], - "time": "2024-09-08T23:32:52+00:00" - }, - { - "name": "pestphp/pest-plugin-mutate", - "version": "v3.0.5", - "source": { - "type": "git", - "url": "https://github.com/pestphp/pest-plugin-mutate.git", - "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/pestphp/pest-plugin-mutate/zipball/e10dbdc98c9e2f3890095b4fe2144f63a5717e08", - "reference": "e10dbdc98c9e2f3890095b4fe2144f63a5717e08", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^5.2.0", - "pestphp/pest-plugin": "^3.0.0", - "php": "^8.2", - "psr/simple-cache": "^3.0.0" - }, - "require-dev": { - "pestphp/pest": "^3.0.8", - "pestphp/pest-dev-tools": "^3.0.0", - "pestphp/pest-plugin-type-coverage": "^3.0.0" - }, - "type": "library", + "extra": { + "laravel": { + "providers": [ + "NunoMaduro\\Collision\\Adapters\\Laravel\\CollisionServiceProvider" + ] + }, + "branch-alias": { + "dev-8.x": "8.x-dev" + } + }, "autoload": { + "files": [ + "./src/Adapters/Phpunit/Autoload.php" + ], "psr-4": { - "Pest\\Mutate\\": "src/" + "NunoMaduro\\Collision\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -6991,24 +6520,26 @@ ], "authors": [ { - "name": "Sandro Gehri", - "email": "sandrogehri@gmail.com" + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" } ], - "description": "Mutates your code to find untested cases", + "description": "Cli error handling for console/command-line PHP applications.", "keywords": [ - "framework", - "mutate", - "mutation", - "pest", + "artisan", + "cli", + "command-line", + "console", + "error", + "handling", + "laravel", + "laravel-zero", "php", - "plugin", - "test", - "testing", - "unit" + "symfony" ], "support": { - "source": "https://github.com/pestphp/pest-plugin-mutate/tree/v3.0.5" + "issues": "https://github.com/nunomaduro/collision/issues", + "source": "https://github.com/nunomaduro/collision" }, "funding": [ { @@ -7016,15 +6547,15 @@ "type": "custom" }, { - "url": "https://github.com/gehrisandro", + "url": "https://github.com/nunomaduro", "type": "github" }, { - "url": "https://github.com/nunomaduro", - "type": "github" + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" } ], - "time": "2024-09-22T07:54:40+00:00" + "time": "2024-10-15T16:06:32+00:00" }, { "name": "phar-io/manifest", @@ -7144,240 +6675,18 @@ }, "time": "2022-02-21T01:04:05+00:00" }, - { - "name": "phpdocumentor/reflection-common", - "version": "2.2.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-2.x": "2.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "Common reflection classes used by phpdocumentor to reflect the code structure", - "homepage": "http://www.phpdoc.org", - "keywords": [ - "FQSEN", - "phpDocumentor", - "phpdoc", - "reflection", - "static analysis" - ], - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", - "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" - }, - "time": "2020-06-27T09:03:43+00:00" - }, - { - "name": "phpdocumentor/reflection-docblock", - "version": "5.4.1", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "reference": "9d07b3f7fdcf5efec5d1609cba3c19c5ea2bdc9c", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.1", - "ext-filter": "*", - "php": "^7.4 || ^8.0", - "phpdocumentor/reflection-common": "^2.2", - "phpdocumentor/type-resolver": "^1.7", - "phpstan/phpdoc-parser": "^1.7", - "webmozart/assert": "^1.9.1" - }, - "require-dev": { - "mockery/mockery": "~1.3.5", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-webmozart-assert": "^1.2", - "phpunit/phpunit": "^9.5", - "vimeo/psalm": "^5.13" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - }, - { - "name": "Jaap van Otterdijk", - "email": "opensource@ijaap.nl" - } - ], - "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "support": { - "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.4.1" - }, - "time": "2024-05-21T05:55:05+00:00" - }, - { - "name": "phpdocumentor/type-resolver", - "version": "1.9.0", - "source": { - "type": "git", - "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/1fb5ba8d045f5dd984ebded5b1cc66f29459422d", - "reference": "1fb5ba8d045f5dd984ebded5b1cc66f29459422d", - "shasum": "" - }, - "require": { - "doctrine/deprecations": "^1.0", - "php": "^7.3 || ^8.0", - "phpdocumentor/reflection-common": "^2.0", - "phpstan/phpdoc-parser": "^1.18" - }, - "require-dev": { - "ext-tokenizer": "*", - "phpbench/phpbench": "^1.2", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^9.5", - "rector/rector": "^0.13.9", - "vimeo/psalm": "^4.25" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - } - }, - "autoload": { - "psr-4": { - "phpDocumentor\\Reflection\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Mike van Riel", - "email": "me@mikevanriel.com" - } - ], - "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "support": { - "issues": "https://github.com/phpDocumentor/TypeResolver/issues", - "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.9.0" - }, - "time": "2024-11-03T20:11:34+00:00" - }, - { - "name": "phpstan/phpdoc-parser", - "version": "1.33.0", - "source": { - "type": "git", - "url": "https://github.com/phpstan/phpdoc-parser.git", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", - "shasum": "" - }, - "require": { - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "doctrine/annotations": "^2.0", - "nikic/php-parser": "^4.15", - "php-parallel-lint/php-parallel-lint": "^1.2", - "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^1.5", - "phpstan/phpstan-phpunit": "^1.1", - "phpstan/phpstan-strict-rules": "^1.0", - "phpunit/phpunit": "^9.5", - "symfony/process": "^5.2" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPStan\\PhpDocParser\\": [ - "src/" - ] - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "description": "PHPDoc parser with support for nullable, intersection and generic types", - "support": { - "issues": "https://github.com/phpstan/phpdoc-parser/issues", - "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" - }, - "time": "2024-10-13T11:25:22+00:00" - }, { "name": "phpunit/php-code-coverage", - "version": "11.0.7", + "version": "11.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca" + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f7f08030e8811582cc459871d28d6f5a1a4d35ca", - "reference": "f7f08030e8811582cc459871d28d6f5a1a4d35ca", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/418c59fd080954f8c4aa5631d9502ecda2387118", + "reference": "418c59fd080954f8c4aa5631d9502ecda2387118", "shasum": "" }, "require": { @@ -7396,7 +6705,7 @@ "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^11.4.1" + "phpunit/phpunit": "^11.5.0" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -7434,7 +6743,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.7" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.8" }, "funding": [ { @@ -7442,7 +6751,7 @@ "type": "github" } ], - "time": "2024-10-09T06:21:38+00:00" + "time": "2024-12-11T12:34:27+00:00" }, { "name": "phpunit/php-file-iterator", @@ -7691,16 +7000,16 @@ }, { "name": "phpunit/phpunit", - "version": "11.4.3", + "version": "11.5.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76" + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e8e8ed1854de5d36c088ec1833beae40d2dedd76", - "reference": "e8e8ed1854de5d36c088ec1833beae40d2dedd76", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3", + "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3", "shasum": "" }, "require": { @@ -7710,25 +7019,26 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.0", + "myclabs/deep-copy": "^1.12.1", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=8.2", - "phpunit/php-code-coverage": "^11.0.7", + "phpunit/php-code-coverage": "^11.0.8", "phpunit/php-file-iterator": "^5.1.0", "phpunit/php-invoker": "^5.0.1", "phpunit/php-text-template": "^4.0.1", "phpunit/php-timer": "^7.0.1", "sebastian/cli-parser": "^3.0.2", - "sebastian/code-unit": "^3.0.1", - "sebastian/comparator": "^6.1.1", + "sebastian/code-unit": "^3.0.2", + "sebastian/comparator": "^6.2.1", "sebastian/diff": "^6.0.2", "sebastian/environment": "^7.2.0", - "sebastian/exporter": "^6.1.3", + "sebastian/exporter": "^6.3.0", "sebastian/global-state": "^7.0.2", "sebastian/object-enumerator": "^6.0.1", "sebastian/type": "^5.1.0", - "sebastian/version": "^5.0.2" + "sebastian/version": "^5.0.2", + "staabm/side-effects-detector": "^1.0.5" }, "suggest": { "ext-soap": "To be able to generate mocks based on WSDL files" @@ -7739,7 +7049,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "11.4-dev" + "dev-main": "11.5-dev" } }, "autoload": { @@ -7771,7 +7081,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/11.4.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2" }, "funding": [ { @@ -7787,7 +7097,7 @@ "type": "tidelift" } ], - "time": "2024-10-28T13:07:50+00:00" + "time": "2024-12-21T05:51:08+00:00" }, { "name": "sebastian/cli-parser", @@ -7848,23 +7158,23 @@ }, { "name": "sebastian/code-unit", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "6bb7d09d6623567178cf54126afa9c2310114268" + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/6bb7d09d6623567178cf54126afa9c2310114268", - "reference": "6bb7d09d6623567178cf54126afa9c2310114268", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", + "reference": "ee88b0cdbe74cf8dd3b54940ff17643c0d6543ca", "shasum": "" }, "require": { "php": ">=8.2" }, "require-dev": { - "phpunit/phpunit": "^11.0" + "phpunit/phpunit": "^11.5" }, "type": "library", "extra": { @@ -7893,7 +7203,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", "security": "https://github.com/sebastianbergmann/code-unit/security/policy", - "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.1" + "source": "https://github.com/sebastianbergmann/code-unit/tree/3.0.2" }, "funding": [ { @@ -7901,7 +7211,7 @@ "type": "github" } ], - "time": "2024-07-03T04:44:28+00:00" + "time": "2024-12-12T09:59:06+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -8227,16 +7537,16 @@ }, { "name": "sebastian/exporter", - "version": "6.1.3", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e" + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", - "reference": "c414673eee9a8f9d51bbf8d61fc9e3ef1e85b20e", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/3473f61172093b2da7de1fb5782e1f24cc036dc3", + "reference": "3473f61172093b2da7de1fb5782e1f24cc036dc3", "shasum": "" }, "require": { @@ -8245,7 +7555,7 @@ "sebastian/recursion-context": "^6.0" }, "require-dev": { - "phpunit/phpunit": "^11.2" + "phpunit/phpunit": "^11.3" }, "type": "library", "extra": { @@ -8293,7 +7603,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", "security": "https://github.com/sebastianbergmann/exporter/security/policy", - "source": "https://github.com/sebastianbergmann/exporter/tree/6.1.3" + "source": "https://github.com/sebastianbergmann/exporter/tree/6.3.0" }, "funding": [ { @@ -8301,7 +7611,7 @@ "type": "github" } ], - "time": "2024-07-03T04:56:19+00:00" + "time": "2024-12-05T09:17:50+00:00" }, { "name": "sebastian/global-state", @@ -8712,22 +8022,75 @@ ], "time": "2024-10-09T05:16:32+00:00" }, + { + "name": "staabm/side-effects-detector", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/staabm/side-effects-detector.git", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/staabm/side-effects-detector/zipball/d8334211a140ce329c13726d4a715adbddd0a163", + "reference": "d8334211a140ce329c13726d4a715adbddd0a163", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^1.12.6", + "phpunit/phpunit": "^9.6.21", + "symfony/var-dumper": "^5.4.43", + "tomasvotruba/type-coverage": "1.0.0", + "tomasvotruba/unused-public": "1.0.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A static analysis tool to detect side effects in PHP code", + "keywords": [ + "static analysis" + ], + "support": { + "issues": "https://github.com/staabm/side-effects-detector/issues", + "source": "https://github.com/staabm/side-effects-detector/tree/1.0.5" + }, + "funding": [ + { + "url": "https://github.com/staabm", + "type": "github" + } + ], + "time": "2024-10-20T05:08:20+00:00" + }, { "name": "symfony/yaml", - "version": "v7.1.6", + "version": "v7.2.0", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671" + "reference": "099581e99f557e9f16b43c5916c26380b54abb22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", - "reference": "3ced3f29e4f0d6bce2170ff26719f1fe9aacc671", + "url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22", + "reference": "099581e99f557e9f16b43c5916c26380b54abb22", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3.0", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -8765,7 +8128,7 @@ "description": "Loads and dumps YAML files", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/yaml/tree/v7.1.6" + "source": "https://github.com/symfony/yaml/tree/v7.2.0" }, "funding": [ { @@ -8781,66 +8144,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" - }, - { - "name": "ta-tikoma/phpunit-architecture-test", - "version": "0.8.4", - "source": { - "type": "git", - "url": "https://github.com/ta-tikoma/phpunit-architecture-test.git", - "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ta-tikoma/phpunit-architecture-test/zipball/89f0dea1cb0f0d5744d3ec1764a286af5e006636", - "reference": "89f0dea1cb0f0d5744d3ec1764a286af5e006636", - "shasum": "" - }, - "require": { - "nikic/php-parser": "^4.18.0 || ^5.0.0", - "php": "^8.1.0", - "phpdocumentor/reflection-docblock": "^5.3.0", - "phpunit/phpunit": "^10.5.5 || ^11.0.0", - "symfony/finder": "^6.4.0 || ^7.0.0" - }, - "require-dev": { - "laravel/pint": "^1.13.7", - "phpstan/phpstan": "^1.10.52" - }, - "type": "library", - "autoload": { - "psr-4": { - "PHPUnit\\Architecture\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ni Shi", - "email": "futik0ma011@gmail.com" - }, - { - "name": "Nuno Maduro", - "email": "enunomaduro@gmail.com" - } - ], - "description": "Methods for testing application architecture", - "keywords": [ - "architecture", - "phpunit", - "stucture", - "test", - "testing" - ], - "support": { - "issues": "https://github.com/ta-tikoma/phpunit-architecture-test/issues", - "source": "https://github.com/ta-tikoma/phpunit-architecture-test/tree/0.8.4" - }, - "time": "2024-01-05T14:10:56+00:00" + "time": "2024-10-23T06:56:12+00:00" }, { "name": "theseer/tokenizer", diff --git a/database/factories/CustomerFactory.php b/database/factories/CustomerFactory.php index 6b0a9db..c83cdbd 100644 --- a/database/factories/CustomerFactory.php +++ b/database/factories/CustomerFactory.php @@ -16,48 +16,11 @@ class CustomerFactory extends Factory */ public function definition(): array { - $pekerjaan = [ - 'SKMHT', - 'APHT', - 'Fidusia', - 'Jual beli', - 'Hibah', - 'Turun waris', - 'Aphb', - 'Pendirian PT', - 'Pendirian CV', - 'Pendirian yayasan', - 'Pendirian PT perorangan', - 'Pendirian akta cabang', - 'Perubahan PT', - 'Perub CV', - 'Perub Yayasan', - 'Pecah sertifikat', - 'Pengeringan', - 'PBG', - 'Peningkatan Hak' - ]; return [ 'name' => fake()->name(), 'phone' => fake()->phoneNumber(), 'alamat' => fake()->address(), - 'kategori' => fake()->randomElement(['Bank', 'Perorangan']), - 'bank' => fake()->randomElement([ - 'BPR BBA', - 'BPR Pala Pusat', - 'BPR Pala Cabang', - 'BPR Danamas Prime', - 'BPR Arum Mandiri', - 'BPRS Madina Mandiri', - 'BMT Sejahtera Ummat', - ]), - 'pekerjaan' => fake()->randomElement($pekerjaan), - 'sertifikat' => fake()->randomElement(['SHM', 'SHU', 'HIBAH']), - 'nilai_transaksi' => fake()->randomFloat(2, 1000000, 1000000000), - 'harga_real' => fake()->randomFloat(2, 1000000, 1000000000), - 'harga_kesepakatan' => fake()->randomFloat(2, 1000000, 1000000000), - 'data_pajak_pembeli' => fake()->randomFloat(2, 1000000, 1000000000), - 'data_pajak_penjual' => fake()->randomFloat(2, 1000000, 1000000000), + ]; } } diff --git a/database/migrations/2024_11_01_021016_create_customers_table.php b/database/migrations/2024_11_01_021016_create_customers_table.php index 7495027..f2ab32f 100644 --- a/database/migrations/2024_11_01_021016_create_customers_table.php +++ b/database/migrations/2024_11_01_021016_create_customers_table.php @@ -16,15 +16,6 @@ public function up(): void $table->string('name', 100); $table->string('phone', 20); $table->string('alamat', 255)->nullable(); - $table->string('kategori', 100)->nullable(); - $table->text('pekerjaan')->nullable(); - $table->string('bank', 100)->nullable(); - $table->string('sertifikat', 50)->nullable(); - $table->integer('nilai_transaksi')->nullable(); - $table->integer('harga_real')->nullable(); - $table->integer('harga_kesepakatan')->nullable(); - $table->integer('data_pajak_pembeli')->nullable(); - $table->integer('data_pajak_penjual')->nullable(); $table->timestamps(); }); } From 38011508726b4f289a2e02d14b99d6764131608d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 8 Jan 2025 11:50:27 +0700 Subject: [PATCH 059/184] fix customer delete --- app/Http/Controllers/CustomerController.php | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index b1cf64f..0b7ebb1 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -19,26 +19,24 @@ class CustomerController extends Controller public function index(Request $request) { - // Validate input + $validated = $request->validate([ 'name' => 'nullable|string|min:3', 'phone' => 'nullable|string|min:4', ]); - // Initialize the query $query = Customer::with('orders'); - // Filter by name if provided if (!empty($validated['name'])) { $query->where('name', 'like', '%' . $validated['name'] . '%'); } - // Filter by phone if provided if (!empty($validated['phone'])) { $query->where('phone', 'like', '%' . $validated['phone'] . '%'); } - // Paginate the results + $query->orderBy('created_at', 'desc'); + $customers = $query->paginate(25); return response()->json($customers); @@ -81,9 +79,12 @@ public function update(Request $request, Customer $customer) public function destroy(Customer $customer) { $customer = Customer::find($customer->id); - $customer->orders()->jobdesks()->delete(); + foreach ($customer->orders as $order) { + $order->jobdesks()->delete(); // Pastikan ada relasi jobdesks() di model Order + } $customer->orders()->delete(); $customer->delete(); + return response()->json($customer); } } From 184396c7e52f0c4ac50aba4a552fd2f0c13ded38 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 8 Jan 2025 15:35:13 +0700 Subject: [PATCH 060/184] update order --- app/Http/Controllers/OrderController.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index f1fc2bb..a620bf4 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -20,21 +20,18 @@ class OrderController extends Controller ]; public function index(Request $request) { - // Ambil parameter query dari request + $customerId = $request->query('customer_id'); $name = $request->query('name'); $status = $request->query('status'); $status = isset($status) ? $status : null; - // Mulai query dasar $query = Order::with('customer', 'jobdesks'); - // Filter berdasarkan customer_id jika ada if ($customerId) { $query->where('customer_id', $customerId); } - // Filter berdasarkan nama customer jika parameter name diberikan dan panjangnya > 2 if ($name && strlen($name) > 2) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); @@ -58,7 +55,8 @@ public function index(Request $request) })->orWhereDoesntHave('jobdesks'); } - // Paginate hasil + $query->orderBy('created_at', 'desc'); + $orders = $query->paginate(25); return response()->json($orders); From fb266f6bc47123b8259b359d950a854e96a6c63f Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 8 Jan 2025 20:20:18 +0700 Subject: [PATCH 061/184] add table data & product --- app/Http/Controllers/SettingController.php | 19 +- ...024_12_14_102650_create_settings_table.php | 2 +- ...2025_01_08_201355_create_product_table.php | 32 +++ .../2025_01_08_201655_create_data_table.php | 29 +++ database/seeders/DatabaseSeeder.php | 224 ++++++++++++++++-- 5 files changed, 276 insertions(+), 30 deletions(-) create mode 100644 database/migrations/2025_01_08_201355_create_product_table.php create mode 100644 database/migrations/2025_01_08_201655_create_data_table.php diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 09c0958..88ff062 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -14,20 +14,21 @@ class SettingController extends Controller /** * Display the settings. */ - public function index(request $request) + public function index(Request $request) { $setting_key = $request->get('setting_key'); - $query = Setting::query(); + $settings = Setting::all(); - if ($setting_key) { - $query->where('setting_key', $setting_key); - } else { - $query->orderBy('setting_key', 'asc'); + $datas = []; + foreach ($settings as $setting) { + $datas[$setting->setting_key] = $setting->setting_value; // Gunakan 'setting_key' dari objek setting } - $settings = $query->get(); + if ($setting_key && isset($datas[$setting_key])) { + return response()->json([$setting_key => $datas[$setting_key]]); + } - return response()->json($settings); + return response()->json($datas); } /** @@ -41,7 +42,7 @@ public function store(Request $request) 'app_description' => 'nullable|string|max:500', 'alamat' => 'nullable|string|max:255', 'banks' => 'nullable|string|max:2000', - 'pekerjaan' => 'nullable|string|max:2000', + 'pekerjaan' => 'nullable|string|max:10000', 'pdf_sample' => 'nullable', 'email' => 'nullable|email|max:255', ]); diff --git a/database/migrations/2024_12_14_102650_create_settings_table.php b/database/migrations/2024_12_14_102650_create_settings_table.php index b45b583..cf8fb6c 100644 --- a/database/migrations/2024_12_14_102650_create_settings_table.php +++ b/database/migrations/2024_12_14_102650_create_settings_table.php @@ -14,7 +14,7 @@ public function up(): void Schema::create('settings', function (Blueprint $table) { $table->id(); $table->string('setting_key')->unique(); - $table->text('setting_value')->nullable(); + $table->longText('setting_value')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2025_01_08_201355_create_product_table.php b/database/migrations/2025_01_08_201355_create_product_table.php new file mode 100644 index 0000000..1e094af --- /dev/null +++ b/database/migrations/2025_01_08_201355_create_product_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('name'); + $table->string('customer_id'); + $table->string('price'); + $table->text('description'); + $table->text('data'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('product'); + } +}; diff --git a/database/migrations/2025_01_08_201655_create_data_table.php b/database/migrations/2025_01_08_201655_create_data_table.php new file mode 100644 index 0000000..b8724eb --- /dev/null +++ b/database/migrations/2025_01_08_201655_create_data_table.php @@ -0,0 +1,29 @@ +id(); + $table->string('name'); + $table->string('type'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('data'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 27c3087..3c52114 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -79,31 +79,215 @@ public function run(): void ]); } } - // { name: 'SKMHT' }, - // { name: 'APHT'}, - // { name: 'Fidusia' }, - // { name: 'Jual beli' }, - // { name: 'Hibah' }, - // { name: 'Turun waris' }, - // { name: 'Aphb' }, - // { name: 'Pendirian PT' }, - // { name: 'Pendirian CV' }, - // { name: 'Pendirian yayasan' }, - // { name: 'Pendirian PT perorangan' }, - // { name: 'Pendirian akta cabang' }, - // { name: 'Perubahan PT' }, - // { name: 'Perub CV' }, - // { name: 'Perub Yayasan' }, - // { name: 'Pecah sertifikat' }, - // { name: 'Pengeringan' }, - // { name: 'PBG' }, - // { name: 'Peningkatan Hak' }, + $pekerjaan = [ + 'Perjanjian Kredit' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Yang Mengerjakan' => 'string', + 'Jumlah Pinjaman' => 'decimal', + 'Lain-lain' => 'string', + ], + 'SKMHT' => [ + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nomor Agunan' => 'string', + 'NIB' => 'string', + 'NOP' => 'string', + 'Nama Pemilik Agunan' => 'string', + 'Kode Sertifikat' => 'string', + 'Nomor Seri' => 'string', + 'Jumlah Pengikatan' => 'decimal', + 'Tanggal Habis SKMHT' => 'date', + ], + 'APHT' => [ + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nomor Agunan' => 'string', + 'NIB' => 'string', + 'NOP' => 'string', + 'Nama Pemilik Agunan' => 'string', + 'Kode Sertifikat' => 'string', + 'Nomor Seri' => 'string', + 'Jumlah Pengikatan' => 'decimal', + ], + 'Fidusia' => [ + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Jenis Agunan' => 'string', + 'Keterangan Objek' => 'string', + 'Bukti Kepemilikan Objek' => 'string', + 'Nilai Objek' => 'decimal', + 'Pemilik Agunan' => 'string', + 'Nilai Penjaminan' => 'decimal', + 'NPWP' => 'string', + 'Tanggal Habis SKMHT' => 'date', + ], + 'Jual Beli' => [ + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Penjual' => 'string', + 'Nama Pembeli' => 'string', + 'Sertifikat' => 'string', + 'Lokasi Tanah' => 'string', + 'Nilai Jual Beli' => 'decimal', + 'Nilai SSB' => 'decimal', + 'Nilai SSP' => 'decimal', + 'Keterangan PPJB' => 'string', + 'Keterangan Kuasa Menjual' => 'string', + 'Harga Real' => 'decimal', + 'Harga Kesepakatan' => 'decimal', + ], + 'Hibah' => [ + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Penjual' => 'string', + 'Nama Pembeli' => 'string', + 'Sertifikat' => 'string', + 'Lokasi Tanah' => 'string', + 'Nilai Jual Beli' => 'decimal', + 'Nilai SSB' => 'decimal', + 'Nilai SSP' => 'decimal', + 'Keterangan PPJB' => 'string', + 'Keterangan Kuasa Menjual' => 'string', + 'Harga Real' => 'decimal', + 'Harga Kesepakatan' => 'decimal', + ], + 'Turun Waris' => [ + 'Berkas Masuk' => 'string', + 'Pewaris' => 'string', + 'Ahli Waris' => 'string', + 'Penerima Waris' => 'string', + 'Lokasi Tanah' => 'string', + 'Nilai Pajak' => 'decimal', + 'Berkas Kembali' => 'string', + 'Masuk BPN' => 'string', + 'Tanggal Akad' => 'date', + ], + 'Pecah' => [ + 'Tanggal Masuk Berkas' => 'date', + 'Nama Pemilik Sertifikat' => 'string', + 'Jumlah Pecah' => 'decimal', + 'Keterangan Agunan' => 'string', + 'Keterangan Berkas' => 'string', + 'Tanggal Masuk BPN' => 'date', + ], + 'Pendirian PT' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Direktur' => 'string', + 'Nama Komisaris' => 'string', + 'NPWP Direktur' => 'string', + 'NPWP Komisaris' => 'string', + 'Nama Pemilik Manfaat' => 'string', + 'Kedudukan PT' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Pendirian CV' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Persero Aktif' => 'string', + 'Nama Persero Pasif' => 'string', + 'NPWP Persero Aktif' => 'string', + 'NPWP Persero Pasif' => 'string', + 'Kedudukan PT' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Pendirian Yayasan' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Pembina' => 'string', + 'Nama Ketua' => 'string', + 'Nama Wakil' => 'string', + 'Nama Bendahara' => 'string', + 'Lain-lain' => 'string', + 'NPWP Yayasan' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Pendirian PT Perseorangan' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Direktur' => 'string', + 'NPWP Direktur' => 'string', + 'Kedudukan PT' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Perubahan PT' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Direktur' => 'string', + 'Nama Komisaris' => 'string', + 'NPWP Direktur' => 'string', + 'NPWP Komisaris' => 'string', + 'Nama Pemilik Manfaat' => 'string', + 'Kedudukan PT' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Perubahan CV' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Persero Aktif' => 'string', + 'Nama Persero Pasif' => 'string', + 'NPWP Persero Aktif' => 'string', + 'NPWP Persero Pasif' => 'string', + 'Kedudukan PT' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Perubahan Yayasan' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Pembina' => 'string', + 'Nama Ketua' => 'string', + 'Nama Wakil' => 'string', + 'Nama Bendahara' => 'string', + 'Lain-lain' => 'string', + 'NPWP Yayasan' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + 'Perubahan PT Perseorangan' => [ + 'Judul Akta' => 'string', + 'Nomor Akta' => 'string', + 'Tanggal Akta' => 'date', + 'Nama Direktur' => 'string', + 'NPWP Direktur' => 'string', + 'Kedudukan PT' => 'string', + 'Biaya' => 'decimal', + 'Keterangan' => 'string', + 'Tanggal Upload' => 'date', + ], + ]; Setting::create(['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT']); Setting::create(['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online']); Setting::create(['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur']); Setting::create(['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf']); Setting::create(['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com']); Setting::create(['setting_key' => 'banks', 'setting_value' => 'BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat']); - Setting::create(['setting_key' => 'pekerjaan', 'setting_value' => 'SKMHT, APHT, Fidusia, Jual beli, Hibah, Turun waris, Aphb, Pendirian PT, Pendirian CV, Pendirian yayasan, Pendirian PT perorangan, Pendirian akta cabang, Perubahan PT, Perub CV, Perub Yayasan, Pecah sertifikat, Pengeringan, PBG, Peningkatan Hak']); + Setting::create( + [ + 'setting_key' => 'pekerjaan', + 'setting_value' => json_encode($pekerjaan) + ] + ); } } From 1d58634f9faf260f286f48e030dc590336f585f9 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 8 Jan 2025 23:11:48 +0700 Subject: [PATCH 062/184] rename table --- app/Http/Controllers/ProductController.php | 72 ++ app/Models/Data.php | 17 + app/Models/Product.php | 18 + app/Models/Setting.php | 2 +- database/factories/DataFactory.php | 20 + database/factories/ProductFactory.php | 21 + ...25_01_08_224038_create_products_table.php} | 5 +- ... 2025_01_08_224129_create_datas_table.php} | 5 +- database/seeders/DatabaseSeeder.php | 682 ++++++++++++------ routes/api.php | 4 +- 10 files changed, 634 insertions(+), 212 deletions(-) create mode 100644 app/Http/Controllers/ProductController.php create mode 100644 app/Models/Data.php create mode 100644 app/Models/Product.php create mode 100644 database/factories/DataFactory.php create mode 100644 database/factories/ProductFactory.php rename database/migrations/{2025_01_08_201355_create_product_table.php => 2025_01_08_224038_create_products_table.php} (79%) rename database/migrations/{2025_01_08_201655_create_data_table.php => 2025_01_08_224129_create_datas_table.php} (78%) diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php new file mode 100644 index 0000000..b8078f0 --- /dev/null +++ b/app/Http/Controllers/ProductController.php @@ -0,0 +1,72 @@ +json($products); + } + + /** + * Store a newly created product in storage. + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string|max:255', + 'price' => 'required|string|max:255', + 'description' => 'required|string', + 'data' => 'required|string', + ]); + + $product = Product::create($request->all()); + return response()->json($product, 201); + } + + /** + * Display the specified product. + */ + public function show($id) + { + $product = Product::findOrFail($id); + return response()->json($product); + } + + /** + * Update the specified product in storage. + */ + public function update(Request $request, $id) + { + $request->validate([ + 'name' => 'string|max:255', + 'price' => 'string|max:255', + 'description' => 'string', + 'data' => 'string', + ]); + + $product = Product::findOrFail($id); + $product->update($request->all()); + return response()->json($product); + } + + /** + * Remove the specified product from storage. + */ + public function destroy($id) + { + $product = Product::findOrFail($id); + $product->delete(); + return response()->json(null, 204); + } +} diff --git a/app/Models/Data.php b/app/Models/Data.php new file mode 100644 index 0000000..eda7c48 --- /dev/null +++ b/app/Models/Data.php @@ -0,0 +1,17 @@ + $this->faker->word, + 'name' => $this->faker->name, + 'type' => $this->faker->word, + ]; + } +} diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php new file mode 100644 index 0000000..a659f21 --- /dev/null +++ b/database/factories/ProductFactory.php @@ -0,0 +1,21 @@ + $this->faker->word, + 'price' => $this->faker->randomFloat(0, 500000, 5000000), + 'description' => $this->faker->paragraph, + 'data' => $this->faker->text, + ]; + } +} diff --git a/database/migrations/2025_01_08_201355_create_product_table.php b/database/migrations/2025_01_08_224038_create_products_table.php similarity index 79% rename from database/migrations/2025_01_08_201355_create_product_table.php rename to database/migrations/2025_01_08_224038_create_products_table.php index 1e094af..26f37ac 100644 --- a/database/migrations/2025_01_08_201355_create_product_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -11,10 +11,9 @@ */ public function up(): void { - Schema::create('product', function (Blueprint $table) { + Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); - $table->string('customer_id'); $table->string('price'); $table->text('description'); $table->text('data'); @@ -27,6 +26,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('product'); + Schema::dropIfExists('products'); } }; diff --git a/database/migrations/2025_01_08_201655_create_data_table.php b/database/migrations/2025_01_08_224129_create_datas_table.php similarity index 78% rename from database/migrations/2025_01_08_201655_create_data_table.php rename to database/migrations/2025_01_08_224129_create_datas_table.php index b8724eb..7f0471c 100644 --- a/database/migrations/2025_01_08_201655_create_data_table.php +++ b/database/migrations/2025_01_08_224129_create_datas_table.php @@ -11,8 +11,9 @@ */ public function up(): void { - Schema::create('data', function (Blueprint $table) { + Schema::create('datas', function (Blueprint $table) { $table->id(); + $table->string('key'); $table->string('name'); $table->string('type'); $table->timestamps(); @@ -24,6 +25,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('data'); + Schema::dropIfExists('datas'); } }; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 3c52114..0846049 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -7,9 +7,10 @@ use App\Models\User; use App\Models\Order; use App\Models\Setting; +use App\Models\Product; +use App\Models\Data; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; -use Pest\ArchPresets\Custom; class DatabaseSeeder extends Seeder { @@ -18,6 +19,464 @@ class DatabaseSeeder extends Seeder */ public function run(): void { + + $products = [ + 'perjanjian_kredit' => [ + 'title' => 'Perjanjian Kredit', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'yang_mengerjakan', + 'jumlah_pinjaman', + 'lain_lain', + ], + ], + 'skmht' => [ + 'title' => 'SKMHT', + 'data' => [ + 'nomor_akta', + 'tanggal_akta', + 'nomor_agunan', + 'nib', + 'nop', + 'nama_pemilik_agunan', + 'kode_sertifikat', + 'nomor_seri', + 'jumlah_pengikatan', + 'tanggal_habis_skmht', + ], + ], + 'apht' => [ + 'title' => 'APHT', + 'data' => [ + 'nomor_akta', + 'tanggal_akta', + 'nomor_agunan', + 'nib', + 'nop', + 'nama_pemilik_agunan', + 'kode_sertifikat', + 'nomor_seri', + 'jumlah_pengikatan', + ], + ], + 'fidusia' => [ + 'title' => 'Fidusia', + 'data' => [ + 'nomor_akta', + 'tanggal_akta', + 'jenis_agunan', + 'keterangan_objek', + 'bukti_kepemilikan_objek', + 'nilai_objek', + 'pemilik_agunan', + 'nilai_penjaminan', + 'npwp', + 'tanggal_habis_skmht', + ], + ], + 'jual_beli' => [ + 'title' => 'Jual Beli', + 'data' => [ + 'nomor_akta', + 'tanggal_akta', + 'nama_penjual', + 'nama_pembeli', + 'sertifikat', + 'lokasi_tanah', + 'nilai_jual_beli', + 'nilai_ssb', + 'nilai_ssp', + 'keterangan_ppjb', + 'keterangan_kuasa_menjual', + 'harga_real', + 'harga_kesepakatan', + ], + ], + 'hibah' => [ + 'title' => 'Hibah', + 'data' => [ + 'nomor_akta', + 'tanggal_akta', + 'nama_penjual', + 'nama_pembeli', + 'sertifikat', + 'lokasi_tanah', + 'nilai_jual_beli', + 'nilai_ssb', + 'nilai_ssp', + 'keterangan_ppjb', + 'keterangan_kuasa_menjual', + 'harga_real', + 'harga_kesepakatan', + ], + ], + 'turun_waris' => [ + 'title' => 'Turun Waris', + 'data' => [ + 'berkas_masuk', + 'pewaris', + 'ahli_waris', + 'penerima_waris', + 'lokasi_tanah', + 'nilai_pajak', + 'berkas_kembali', + 'masuk_bpn', + 'tanggal_akad', + ], + ], + 'pecah' => [ + 'title' => 'Pecah', + 'data' => [ + 'tanggal_masuk_berkas', + 'nama_pemilik_sertifikat', + 'jumlah_pecah', + 'keterangan_agunan', + 'keterangan_berkas', + 'tanggal_masuk_bpn', + ], + ], + 'pendirian_pt' => [ + 'title' => 'Pendirian PT', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_direktur', + 'nama_komisaris', + 'npwp_direktur', + 'npwp_komisaris', + 'nama_pemilik_manfaat', + 'kedudukan_pt', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'pendirian_cv' => [ + 'title' => 'Pendirian CV', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_persero_aktif', + 'nama_persero_pasib', + 'npwp_persero_aktif', + 'npwp_persero_pasib', + 'kedudukan_pt', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'pendirian_yayasan' => [ + 'title' => 'Pendirian Yayasan', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_pembina', + 'nama_ketua', + 'nama_wakil', + 'nama_bendahara', + 'lain_lain', + 'npwp_yayasan', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'pendirian_pt_perseorangan' => [ + 'title' => 'Pendirian PT Perseorangan', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_direktur', + 'npwp_direktur', + 'kedudukan_pt', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'perubahan_pt' => [ + 'title' => 'Perubahan PT', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_direktur', + 'nama_komisaris', + 'npwp_direktur', + 'npwp_komisaris', + 'nama_pemilik_manfaat', + 'kedudukan_pt', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'perubahan_cv' => [ + 'title' => 'Perubahan CV', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_persero_aktif', + 'nama_persero_pasib', + 'npwp_persero_aktif', + 'npwp_persero_pasib', + 'kedudukan_pt', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'perubahan_yayasan' => [ + 'title' => 'Perubahan Yayasan', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_pembina', + 'nama_ketua', + 'nama_wakil', + 'nama_bendahara', + 'lain_lain', + 'npwp_yayasan', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + 'perubahan_pt_perseorangan' => [ + 'title' => 'Perubahan PT Perseorangan', + 'data' => [ + 'judul_akta', + 'nomor_akta', + 'tanggal_akta', + 'nama_direktur', + 'npwp_direktur', + 'kedudukan_pt', + 'biaya', + 'keterangan', + 'tanggal_upload', + ], + ], + ]; + $datas = [ + 'judul_akta' => [ + 'title' => 'Judul Akta', + 'type' => 'text' + ], + 'nomor_akta' => [ + 'title' => 'Nomor Akta', + 'type' => 'text' + ], + 'tanggal_akta' => [ + 'title' => 'Tanggal Akta', + 'type' => 'date' + ], + 'yang_mengerjakan' => [ + 'title' => 'Yang Mengerjakan', + 'type' => 'text' + ], + 'jumlah_pinjaman' => [ + 'title' => 'Jumlah Pinjaman', + 'type' => 'number' + ], + 'lain_lain' => [ + 'title' => 'Lain-lain', + 'type' => 'text' + ], + 'tanggal_habis_skmht' => [ + 'title' => 'Tanggal Habis SKMHT', + 'type' => 'date' + ], + 'nomor_agunan' => [ + 'title' => 'Nomor Agunan', + 'type' => 'text' + ], + 'nib' => [ + 'title' => 'NIB', + 'type' => 'text' + ], + 'nop' => [ + 'title' => 'NOP', + 'type' => 'text' + ], + 'nama_pemilik_agunan' => [ + 'title' => 'Nama Pemilik Agunan', + 'type' => 'text' + ], + 'kode_sertifikat' => [ + 'title' => 'Kode Sertifikat', + 'type' => 'text' + ], + 'nomor_seri' => [ + 'title' => 'Nomor Seri', + 'type' => 'text' + ], + 'jumlah_pengikatan' => [ + 'title' => 'Jumlah Pengikatan', + 'type' => 'number' + ], + 'jenis_agunan' => [ + 'title' => 'Jenis Agunan', + 'type' => 'text' + ], + 'keterangan_objek' => [ + 'title' => 'Keterangan Objek', + 'type' => 'text' + ], + 'bukti_kepemilikan_objek' => [ + 'title' => 'Bukti Kepemilikan Objek', + 'type' => 'text' + ], + 'nilai_objek' => [ + 'title' => 'Nilai Objek', + 'type' => 'number' + ], + 'pemilik_agunan' => [ + 'title' => 'Pemilik Agunan', + 'type' => 'text' + ], + 'nilai_penjaminan' => [ + 'title' => 'Nilai Penjaminan', + 'type' => 'number' + ], + 'npwp' => [ + 'title' => 'NPWP', + 'type' => 'text' + ], + 'berkas_masuk' => [ + 'title' => 'Berkas Masuk', + 'type' => 'text' + ], + 'pewaris' => [ + 'title' => 'Pewaris', + 'type' => 'text' + ], + 'ahli_waris' => [ + 'title' => 'Ahli Waris', + 'type' => 'text' + ], + 'penerima_waris' => [ + 'title' => 'Penerima Waris', + 'type' => 'text' + ], + 'lokasi_tanah' => [ + 'title' => 'Lokasi Tanah', + 'type' => 'text' + ], + 'nilai_pajak' => [ + 'title' => 'Nilai Pajak', + 'type' => 'number' + ], + 'berkas_kembali' => [ + 'title' => 'Berkas Kembali', + 'type' => 'text' + ], + 'masuk_bpn' => [ + 'title' => 'Masuk BPN', + 'type' => 'text' + ], + 'tanggal_akad' => [ + 'title' => 'Tanggal Akad', + 'type' => 'date' + ], + 'nama_penjual' => [ + 'title' => 'Nama Penjual', + 'type' => 'text' + ], + 'nama_pembeli' => [ + 'title' => 'Nama Pembeli', + 'type' => 'text' + ], + 'sertifikat' => [ + 'title' => 'Sertifikat', + 'type' => 'text' + ], + 'nilai_jual_beli' => [ + 'title' => 'Nilai Jual Beli', + 'type' => 'number' + ], + 'nilai_ssb' => [ + 'title' => 'Nilai SSB', + 'type' => 'number' + ], + 'nilai_ssp' => [ + 'title' => 'Nilai SSP', + 'type' => 'number' + ], + 'keterangan_ppjb' => [ + 'title' => 'Keterangan PPJB', + 'type' => 'text' + ], + 'keterangan_kuasa_menjual' => [ + 'title' => 'Keterangan Kuasa Menjual', + 'type' => 'text' + ], + 'harga_real' => [ + 'title' => 'Harga Real', + 'type' => 'number' + ], + 'harga_kesepakatan' => [ + 'title' => 'Harga Kesepakatan', + 'type' => 'number' + ], + 'biaya' => [ + 'title' => 'Biaya', + 'type' => 'number' + ], + 'nama_direktur' => [ + 'title' => 'Nama Direktur', + 'type' => 'text' + ], + 'nama_komisaris' => [ + 'title' => 'Nama Komisaris', + 'type' => 'text' + ], + 'nama_pemilik_manfaat' => [ + 'title' => 'Nama Pemilik Manfaat', + 'type' => 'text' + ], + 'kedudukan_pt' => [ + 'title' => 'Kedudukan PT', + 'type' => 'text' + ], + 'nama_persero_aktif' => [ + 'title' => 'Nama Persero Aktif', + 'type' => 'text' + ], + 'nama_persero_pasib' => [ + 'title' => 'Nama Persero Pasif', + 'type' => 'text' + ], + 'nama_pembina' => [ + 'title' => 'Nama Pembina', + 'type' => 'text' + ], + 'nama_ketua' => [ + 'title' => 'Nama Ketua', + 'type' => 'text' + ], + 'nama_wakil' => [ + 'title' => 'Nama Wakil', + 'type' => 'text' + ], + 'nama_bendahara' => [ + 'title' => 'Nama Bendahara', + 'type' => 'text' + ], + 'tanggal_upload' => [ + 'title' => 'Tanggal Upload', + 'type' => 'date' + ], + ]; + User::factory()->create([ 'name' => 'Test Admin', 'email' => 'test@larapi.test', @@ -65,6 +524,22 @@ public function run(): void // Membuat 5 customer $customers = Customer::factory(35)->create(); + foreach ($products as $key => $product) { + Product::factory()->create([ + 'name' => $product['title'], + 'price' => rand(100000, 1000000), + 'data' => implode(',', $product['data']), + ]); + } + + foreach ($datas as $key => $val) { + Data::factory()->create([ + 'key' => $key, + 'name' => $val['title'], + 'type' => $val['type'] + ]); + } + foreach ($customers as $customer) { // Membuat antara 2 hingga 10 order untuk setiap customer $ordersCount = rand(2, 10); @@ -79,215 +554,12 @@ public function run(): void ]); } } - $pekerjaan = [ - 'Perjanjian Kredit' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Yang Mengerjakan' => 'string', - 'Jumlah Pinjaman' => 'decimal', - 'Lain-lain' => 'string', - ], - 'SKMHT' => [ - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nomor Agunan' => 'string', - 'NIB' => 'string', - 'NOP' => 'string', - 'Nama Pemilik Agunan' => 'string', - 'Kode Sertifikat' => 'string', - 'Nomor Seri' => 'string', - 'Jumlah Pengikatan' => 'decimal', - 'Tanggal Habis SKMHT' => 'date', - ], - 'APHT' => [ - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nomor Agunan' => 'string', - 'NIB' => 'string', - 'NOP' => 'string', - 'Nama Pemilik Agunan' => 'string', - 'Kode Sertifikat' => 'string', - 'Nomor Seri' => 'string', - 'Jumlah Pengikatan' => 'decimal', - ], - 'Fidusia' => [ - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Jenis Agunan' => 'string', - 'Keterangan Objek' => 'string', - 'Bukti Kepemilikan Objek' => 'string', - 'Nilai Objek' => 'decimal', - 'Pemilik Agunan' => 'string', - 'Nilai Penjaminan' => 'decimal', - 'NPWP' => 'string', - 'Tanggal Habis SKMHT' => 'date', - ], - 'Jual Beli' => [ - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Penjual' => 'string', - 'Nama Pembeli' => 'string', - 'Sertifikat' => 'string', - 'Lokasi Tanah' => 'string', - 'Nilai Jual Beli' => 'decimal', - 'Nilai SSB' => 'decimal', - 'Nilai SSP' => 'decimal', - 'Keterangan PPJB' => 'string', - 'Keterangan Kuasa Menjual' => 'string', - 'Harga Real' => 'decimal', - 'Harga Kesepakatan' => 'decimal', - ], - 'Hibah' => [ - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Penjual' => 'string', - 'Nama Pembeli' => 'string', - 'Sertifikat' => 'string', - 'Lokasi Tanah' => 'string', - 'Nilai Jual Beli' => 'decimal', - 'Nilai SSB' => 'decimal', - 'Nilai SSP' => 'decimal', - 'Keterangan PPJB' => 'string', - 'Keterangan Kuasa Menjual' => 'string', - 'Harga Real' => 'decimal', - 'Harga Kesepakatan' => 'decimal', - ], - 'Turun Waris' => [ - 'Berkas Masuk' => 'string', - 'Pewaris' => 'string', - 'Ahli Waris' => 'string', - 'Penerima Waris' => 'string', - 'Lokasi Tanah' => 'string', - 'Nilai Pajak' => 'decimal', - 'Berkas Kembali' => 'string', - 'Masuk BPN' => 'string', - 'Tanggal Akad' => 'date', - ], - 'Pecah' => [ - 'Tanggal Masuk Berkas' => 'date', - 'Nama Pemilik Sertifikat' => 'string', - 'Jumlah Pecah' => 'decimal', - 'Keterangan Agunan' => 'string', - 'Keterangan Berkas' => 'string', - 'Tanggal Masuk BPN' => 'date', - ], - 'Pendirian PT' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Direktur' => 'string', - 'Nama Komisaris' => 'string', - 'NPWP Direktur' => 'string', - 'NPWP Komisaris' => 'string', - 'Nama Pemilik Manfaat' => 'string', - 'Kedudukan PT' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Pendirian CV' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Persero Aktif' => 'string', - 'Nama Persero Pasif' => 'string', - 'NPWP Persero Aktif' => 'string', - 'NPWP Persero Pasif' => 'string', - 'Kedudukan PT' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Pendirian Yayasan' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Pembina' => 'string', - 'Nama Ketua' => 'string', - 'Nama Wakil' => 'string', - 'Nama Bendahara' => 'string', - 'Lain-lain' => 'string', - 'NPWP Yayasan' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Pendirian PT Perseorangan' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Direktur' => 'string', - 'NPWP Direktur' => 'string', - 'Kedudukan PT' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Perubahan PT' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Direktur' => 'string', - 'Nama Komisaris' => 'string', - 'NPWP Direktur' => 'string', - 'NPWP Komisaris' => 'string', - 'Nama Pemilik Manfaat' => 'string', - 'Kedudukan PT' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Perubahan CV' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Persero Aktif' => 'string', - 'Nama Persero Pasif' => 'string', - 'NPWP Persero Aktif' => 'string', - 'NPWP Persero Pasif' => 'string', - 'Kedudukan PT' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Perubahan Yayasan' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Pembina' => 'string', - 'Nama Ketua' => 'string', - 'Nama Wakil' => 'string', - 'Nama Bendahara' => 'string', - 'Lain-lain' => 'string', - 'NPWP Yayasan' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - 'Perubahan PT Perseorangan' => [ - 'Judul Akta' => 'string', - 'Nomor Akta' => 'string', - 'Tanggal Akta' => 'date', - 'Nama Direktur' => 'string', - 'NPWP Direktur' => 'string', - 'Kedudukan PT' => 'string', - 'Biaya' => 'decimal', - 'Keterangan' => 'string', - 'Tanggal Upload' => 'date', - ], - ]; + Setting::create(['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT']); Setting::create(['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online']); Setting::create(['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur']); Setting::create(['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf']); Setting::create(['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com']); Setting::create(['setting_key' => 'banks', 'setting_value' => 'BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat']); - Setting::create( - [ - 'setting_key' => 'pekerjaan', - 'setting_value' => json_encode($pekerjaan) - ] - ); } } diff --git a/routes/api.php b/routes/api.php index 105f658..2217026 100644 --- a/routes/api.php +++ b/routes/api.php @@ -9,6 +9,7 @@ use App\Http\Controllers\DashboardController; use App\Http\Controllers\SettingController; use App\Http\Controllers\UserController; +use App\Http\Controllers\ProductController; use App\Http\Controllers\Auth\ProfileController; Route::middleware(['auth:sanctum'])->group(function () { @@ -24,6 +25,7 @@ 'orders' => OrderController::class, 'jobdesks' => JobdeskController::class, 'customers' => CustomerController::class, - 'settings' => SettingController::class + 'settings' => SettingController::class, + 'products' => ProductController::class ]); }); From cca3001a256d69a16a248c970696bc65981fa377 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 9 Jan 2025 00:11:18 +0700 Subject: [PATCH 063/184] membuat model relasi --- app/Http/Controllers/DataController.php | 50 ++++++++++++++ app/Http/Controllers/ProductController.php | 14 +++- app/Models/Data.php | 15 +++-- app/Models/Product.php | 9 +++ app/Policies/DataPolicy.php | 66 +++++++++++++++++++ database/factories/DataFactory.php | 25 +++---- ...> 2025_01_08_231951_create_data_table.php} | 6 +- database/seeders/DataSeeder.php | 17 +++++ database/seeders/DatabaseSeeder.php | 5 +- 9 files changed, 184 insertions(+), 23 deletions(-) create mode 100644 app/Http/Controllers/DataController.php create mode 100644 app/Policies/DataPolicy.php rename database/migrations/{2025_01_08_224129_create_datas_table.php => 2025_01_08_231951_create_data_table.php} (78%) create mode 100644 database/seeders/DataSeeder.php diff --git a/app/Http/Controllers/DataController.php b/app/Http/Controllers/DataController.php new file mode 100644 index 0000000..ffa081b --- /dev/null +++ b/app/Http/Controllers/DataController.php @@ -0,0 +1,50 @@ +transform(function ($product) { + return [ + 'id' => $product->id, + 'name' => $product->name, + 'price' => $product->price, + 'description' => $product->description, + 'data' => $product->getDataKeys(), // Menyertakan data terkait + ]; + }); + + // Mengembalikan response dalam format JSON return response()->json($products); } diff --git a/app/Models/Data.php b/app/Models/Data.php index eda7c48..0b40aa2 100644 --- a/app/Models/Data.php +++ b/app/Models/Data.php @@ -7,11 +7,14 @@ class Data extends Model { - use HasFactory; + /** @use HasFactory<\Database\Factories\DataFactory> */ + use HasFactory; - protected $fillable = [ - 'key', - 'name', - 'type', - ]; + protected $table = 'data'; + + protected $fillable = [ + 'key', + 'value', + 'type' + ]; } diff --git a/app/Models/Product.php b/app/Models/Product.php index 5ffa7ae..cf383ca 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -15,4 +15,13 @@ class Product extends Model 'description', 'data', ]; + + public function getDataKeys() + { + // Memecah string data menjadi array + $keys = explode(',', $this->data); + + // Mengambil data yang sesuai dengan key yang dipisahkan koma + return Data::whereIn('key', $keys)->get(); + } } diff --git a/app/Policies/DataPolicy.php b/app/Policies/DataPolicy.php new file mode 100644 index 0000000..af2d80e --- /dev/null +++ b/app/Policies/DataPolicy.php @@ -0,0 +1,66 @@ + + */ class DataFactory extends Factory { - protected $model = Data::class; - - public function definition() - { - return [ - 'key' => $this->faker->word, - 'name' => $this->faker->name, - 'type' => $this->faker->word, - ]; - } + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + return [ + // + ]; + } } diff --git a/database/migrations/2025_01_08_224129_create_datas_table.php b/database/migrations/2025_01_08_231951_create_data_table.php similarity index 78% rename from database/migrations/2025_01_08_224129_create_datas_table.php rename to database/migrations/2025_01_08_231951_create_data_table.php index 7f0471c..4eeb970 100644 --- a/database/migrations/2025_01_08_224129_create_datas_table.php +++ b/database/migrations/2025_01_08_231951_create_data_table.php @@ -11,10 +11,10 @@ */ public function up(): void { - Schema::create('datas', function (Blueprint $table) { + Schema::create('data', function (Blueprint $table) { $table->id(); $table->string('key'); - $table->string('name'); + $table->string('value'); $table->string('type'); $table->timestamps(); }); @@ -25,6 +25,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('datas'); + Schema::dropIfExists('data'); } }; diff --git a/database/seeders/DataSeeder.php b/database/seeders/DataSeeder.php new file mode 100644 index 0000000..28e9716 --- /dev/null +++ b/database/seeders/DataSeeder.php @@ -0,0 +1,17 @@ + $product) { Product::factory()->create([ 'name' => $product['title'], - 'price' => rand(100000, 1000000), + 'price' => rand(100000, 5000000), + 'description' => '', 'data' => implode(',', $product['data']), ]); } @@ -535,7 +536,7 @@ public function run(): void foreach ($datas as $key => $val) { Data::factory()->create([ 'key' => $key, - 'name' => $val['title'], + 'value' => $val['title'], 'type' => $val['type'] ]); } From 6a3b8324ed6677fa34843fe07ea40926486011d7 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 9 Jan 2025 08:31:38 +0700 Subject: [PATCH 064/184] fix pivot data product --- app/Http/Controllers/ProductController.php | 13 +- app/Models/Data.php | 5 + app/Models/DataProduct.php | 44 ++ app/Models/Product.php | 8 +- database/factories/DataProductFactory.php | 31 ++ database/factories/ProductFactory.php | 1 - ...025_01_08_224038_create_products_table.php | 1 - .../2025_01_08_231951_create_data_table.php | 1 - ...01_09_074553_create_data_product_table.php | 29 ++ database/seeders/DatabaseSeeder.php | 459 +++++++++--------- 10 files changed, 343 insertions(+), 249 deletions(-) create mode 100644 app/Models/DataProduct.php create mode 100644 database/factories/DataProductFactory.php create mode 100644 database/migrations/2025_01_09_074553_create_data_product_table.php diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 9b9a31d..22479a2 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -13,18 +13,7 @@ class ProductController extends Controller public function index(Request $request) { // Mengambil produk dan memuat data terkait - $products = Product::paginate(25); - - // Menambahkan data terkait ke setiap produk - $products->transform(function ($product) { - return [ - 'id' => $product->id, - 'name' => $product->name, - 'price' => $product->price, - 'description' => $product->description, - 'data' => $product->getDataKeys(), // Menyertakan data terkait - ]; - }); + $products = Product::with('dataProducts.data')->paginate(25); // Mengembalikan response dalam format JSON return response()->json($products); diff --git a/app/Models/Data.php b/app/Models/Data.php index 0b40aa2..393ab9b 100644 --- a/app/Models/Data.php +++ b/app/Models/Data.php @@ -17,4 +17,9 @@ class Data extends Model 'value', 'type' ]; + + public function dataProducts() + { + return $this->hasMany(DataProduct::class, 'data_id'); + } } diff --git a/app/Models/DataProduct.php b/app/Models/DataProduct.php new file mode 100644 index 0000000..89efd80 --- /dev/null +++ b/app/Models/DataProduct.php @@ -0,0 +1,44 @@ +belongsTo(Data::class); + } + + /** + * Get the related product. + */ + public function product() + { + return $this->belongsTo(Product::class); + } +} diff --git a/app/Models/Product.php b/app/Models/Product.php index cf383ca..27e339c 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -16,12 +16,8 @@ class Product extends Model 'data', ]; - public function getDataKeys() + public function dataProducts() { - // Memecah string data menjadi array - $keys = explode(',', $this->data); - - // Mengambil data yang sesuai dengan key yang dipisahkan koma - return Data::whereIn('key', $keys)->get(); + return $this->hasMany(DataProduct::class, 'product_id'); } } diff --git a/database/factories/DataProductFactory.php b/database/factories/DataProductFactory.php new file mode 100644 index 0000000..770a36f --- /dev/null +++ b/database/factories/DataProductFactory.php @@ -0,0 +1,31 @@ + Data::factory(), // Create or use an existing Data model + 'product_id' => Product::factory(), // Create or use an existing Product model + ]; + } +} diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php index a659f21..7ceacea 100644 --- a/database/factories/ProductFactory.php +++ b/database/factories/ProductFactory.php @@ -15,7 +15,6 @@ public function definition() 'name' => $this->faker->word, 'price' => $this->faker->randomFloat(0, 500000, 5000000), 'description' => $this->faker->paragraph, - 'data' => $this->faker->text, ]; } } diff --git a/database/migrations/2025_01_08_224038_create_products_table.php b/database/migrations/2025_01_08_224038_create_products_table.php index 26f37ac..b466eaa 100644 --- a/database/migrations/2025_01_08_224038_create_products_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -16,7 +16,6 @@ public function up(): void $table->string('name'); $table->string('price'); $table->text('description'); - $table->text('data'); $table->timestamps(); }); } diff --git a/database/migrations/2025_01_08_231951_create_data_table.php b/database/migrations/2025_01_08_231951_create_data_table.php index 4eeb970..974e5a9 100644 --- a/database/migrations/2025_01_08_231951_create_data_table.php +++ b/database/migrations/2025_01_08_231951_create_data_table.php @@ -15,7 +15,6 @@ public function up(): void $table->id(); $table->string('key'); $table->string('value'); - $table->string('type'); $table->timestamps(); }); } diff --git a/database/migrations/2025_01_09_074553_create_data_product_table.php b/database/migrations/2025_01_09_074553_create_data_product_table.php new file mode 100644 index 0000000..d3ae22f --- /dev/null +++ b/database/migrations/2025_01_09_074553_create_data_product_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('data_id')->constrained()->onDelete('cascade'); + $table->foreignId('product_id')->constrained()->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('data_product'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 90063e6..bfa409a 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -9,6 +9,7 @@ use App\Models\Setting; use App\Models\Product; use App\Models\Data; +use App\Models\DataProduct; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; @@ -24,457 +25,446 @@ public function run(): void 'perjanjian_kredit' => [ 'title' => 'Perjanjian Kredit', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'yang_mengerjakan', - 'jumlah_pinjaman', - 'lain_lain', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 4, // Yang Mengerjakan + 5, // Jumlah Pinjaman + 6, // Lain-lain ], ], 'skmht' => [ 'title' => 'SKMHT', 'data' => [ - 'nomor_akta', - 'tanggal_akta', - 'nomor_agunan', - 'nib', - 'nop', - 'nama_pemilik_agunan', - 'kode_sertifikat', - 'nomor_seri', - 'jumlah_pengikatan', - 'tanggal_habis_skmht', + 2, // Nomor Akta + 3, // Tanggal Akta + 8, // Nomor Agunan + 9, // NIB + 10, // NOP + 11, // Nama Pemilik Agunan + 12, // Kode Sertifikat + 13, // Nomor Seri + 14, // Jumlah Pengikatan + 7, // Tanggal Habis SKMHT ], ], 'apht' => [ 'title' => 'APHT', 'data' => [ - 'nomor_akta', - 'tanggal_akta', - 'nomor_agunan', - 'nib', - 'nop', - 'nama_pemilik_agunan', - 'kode_sertifikat', - 'nomor_seri', - 'jumlah_pengikatan', + 2, // Nomor Akta + 3, // Tanggal Akta + 8, // Nomor Agunan + 9, // NIB + 10, // NOP + 11, // Nama Pemilik Agunan + 12, // Kode Sertifikat + 13, // Nomor Seri + 14, // Jumlah Pengikatan ], ], 'fidusia' => [ 'title' => 'Fidusia', 'data' => [ - 'nomor_akta', - 'tanggal_akta', - 'jenis_agunan', - 'keterangan_objek', - 'bukti_kepemilikan_objek', - 'nilai_objek', - 'pemilik_agunan', - 'nilai_penjaminan', - 'npwp', - 'tanggal_habis_skmht', + 2, // Nomor Akta + 3, // Tanggal Akta + 15, // Jenis Agunan + 16, // Keterangan Objek + 17, // Bukti Kepemilikan Objek + 18, // Nilai Objek + 19, // Pemilik Agunan + 20, // Nilai Penjaminan + 21, // NPWP + 7, // Tanggal Habis SKMHT ], ], 'jual_beli' => [ 'title' => 'Jual Beli', 'data' => [ - 'nomor_akta', - 'tanggal_akta', - 'nama_penjual', - 'nama_pembeli', - 'sertifikat', - 'lokasi_tanah', - 'nilai_jual_beli', - 'nilai_ssb', - 'nilai_ssp', - 'keterangan_ppjb', - 'keterangan_kuasa_menjual', - 'harga_real', - 'harga_kesepakatan', + 2, // Nomor Akta + 3, // Tanggal Akta + 31, // Nama Penjual + 32, // Nama Pembeli + 33, // Sertifikat + 26, // Lokasi Tanah + 34, // Nilai Jual Beli + 35, // Nilai SSB + 36, // Nilai SSP + 37, // Keterangan PPJB + 38, // Keterangan Kuasa Menjual + 39, // Harga Real + 40, // Harga Kesepakatan ], ], 'hibah' => [ 'title' => 'Hibah', 'data' => [ - 'nomor_akta', - 'tanggal_akta', - 'nama_penjual', - 'nama_pembeli', - 'sertifikat', - 'lokasi_tanah', - 'nilai_jual_beli', - 'nilai_ssb', - 'nilai_ssp', - 'keterangan_ppjb', - 'keterangan_kuasa_menjual', - 'harga_real', - 'harga_kesepakatan', + 2, // Nomor Akta + 3, // Tanggal Akta + 31, // Nama Penjual + 32, // Nama Pembeli + 33, // Sertifikat + 26, // Lokasi Tanah + 34, // Nilai Jual Beli + 35, // Nilai SSB + 36, // Nilai SSP + 37, // Keterangan PPJB + 38, // Keterangan Kuasa Menjual + 39, // Harga Real + 40, // Harga Kesepakatan ], ], 'turun_waris' => [ 'title' => 'Turun Waris', 'data' => [ - 'berkas_masuk', - 'pewaris', - 'ahli_waris', - 'penerima_waris', - 'lokasi_tanah', - 'nilai_pajak', - 'berkas_kembali', - 'masuk_bpn', - 'tanggal_akad', + 22, // Berkas Masuk + 23, // Pewaris + 24, // Ahli Waris + 25, // Penerima Waris + 26, // Lokasi Tanah + 27, // Nilai Pajak + 28, // Berkas Kembali + 29, // Masuk BPN + 30, // Tanggal Akad ], ], 'pecah' => [ 'title' => 'Pecah', 'data' => [ - 'tanggal_masuk_berkas', - 'nama_pemilik_sertifikat', - 'jumlah_pecah', - 'keterangan_agunan', - 'keterangan_berkas', - 'tanggal_masuk_bpn', + 1, // Judul Akta + 44, // Nama Pemilik Sertifikat + // Tambahkan elemen lain yang sesuai jika perlu ], ], 'pendirian_pt' => [ 'title' => 'Pendirian PT', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_direktur', - 'nama_komisaris', - 'npwp_direktur', - 'npwp_komisaris', - 'nama_pemilik_manfaat', - 'kedudukan_pt', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 42, // Nama Direktur + 43, // Nama Komisaris + 21, // NPWP Direktur + 21, // NPWP Komisaris + 44, // Nama Pemilik Manfaat + 45, // Kedudukan PT + 41, // Biaya + 52, // Tanggal Upload ], ], 'pendirian_cv' => [ 'title' => 'Pendirian CV', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_persero_aktif', - 'nama_persero_pasib', - 'npwp_persero_aktif', - 'npwp_persero_pasib', - 'kedudukan_pt', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 46, // Nama Persero Aktif + 47, // Nama Persero Pasif + 21, // NPWP Persero Aktif + 21, // NPWP Persero Pasif + 45, // Kedudukan PT + 41, // Biaya + 52, // Tanggal Upload ], ], 'pendirian_yayasan' => [ 'title' => 'Pendirian Yayasan', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_pembina', - 'nama_ketua', - 'nama_wakil', - 'nama_bendahara', - 'lain_lain', - 'npwp_yayasan', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 48, // Nama Pembina + 49, // Nama Ketua + 50, // Nama Wakil + 51, // Nama Bendahara + 6, // Lain-lain + 21, // NPWP Yayasan + 41, // Biaya + 52, // Tanggal Upload ], ], 'pendirian_pt_perseorangan' => [ 'title' => 'Pendirian PT Perseorangan', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_direktur', - 'npwp_direktur', - 'kedudukan_pt', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 42, // Nama Direktur + 21, // NPWP Direktur + 45, // Kedudukan PT + 41, // Biaya + 52, // Tanggal Upload ], ], 'perubahan_pt' => [ 'title' => 'Perubahan PT', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_direktur', - 'nama_komisaris', - 'npwp_direktur', - 'npwp_komisaris', - 'nama_pemilik_manfaat', - 'kedudukan_pt', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 42, // Nama Direktur + 43, // Nama Komisaris + 21, // NPWP Direktur + 21, // NPWP Komisaris + 44, // Nama Pemilik Manfaat + 45, // Kedudukan PT + 41, // Biaya + 52, // Tanggal Upload ], ], 'perubahan_cv' => [ 'title' => 'Perubahan CV', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_persero_aktif', - 'nama_persero_pasib', - 'npwp_persero_aktif', - 'npwp_persero_pasib', - 'kedudukan_pt', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 46, // Nama Persero Aktif + 47, // Nama Persero Pasif + 21, // NPWP Persero Aktif + 21, // NPWP Persero Pasif + 45, // Kedudukan PT + 41, // Biaya + 52, // Tanggal Upload ], ], 'perubahan_yayasan' => [ 'title' => 'Perubahan Yayasan', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_pembina', - 'nama_ketua', - 'nama_wakil', - 'nama_bendahara', - 'lain_lain', - 'npwp_yayasan', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 48, // Nama Pembina + 49, // Nama Ketua + 50, // Nama Wakil + 51, // Nama Bendahara + 6, // Lain-lain + 21, // NPWP Yayasan + 41, // Biaya + 52, // Tanggal Upload ], ], 'perubahan_pt_perseorangan' => [ 'title' => 'Perubahan PT Perseorangan', 'data' => [ - 'judul_akta', - 'nomor_akta', - 'tanggal_akta', - 'nama_direktur', - 'npwp_direktur', - 'kedudukan_pt', - 'biaya', - 'keterangan', - 'tanggal_upload', + 1, // Judul Akta + 2, // Nomor Akta + 3, // Tanggal Akta + 42, // Nama Direktur + 21, // NPWP Direktur + 45, // Kedudukan PT + 41, // Biaya + 52, // Tanggal Upload ], ], ]; $datas = [ - 'judul_akta' => [ + 1 => [ 'title' => 'Judul Akta', 'type' => 'text' ], - 'nomor_akta' => [ + 2 => [ 'title' => 'Nomor Akta', 'type' => 'text' ], - 'tanggal_akta' => [ + 3 => [ 'title' => 'Tanggal Akta', 'type' => 'date' ], - 'yang_mengerjakan' => [ + 4 => [ 'title' => 'Yang Mengerjakan', 'type' => 'text' ], - 'jumlah_pinjaman' => [ + 5 => [ 'title' => 'Jumlah Pinjaman', 'type' => 'number' ], - 'lain_lain' => [ + 6 => [ 'title' => 'Lain-lain', 'type' => 'text' ], - 'tanggal_habis_skmht' => [ + 7 => [ 'title' => 'Tanggal Habis SKMHT', 'type' => 'date' ], - 'nomor_agunan' => [ + 8 => [ 'title' => 'Nomor Agunan', 'type' => 'text' ], - 'nib' => [ + 9 => [ 'title' => 'NIB', 'type' => 'text' ], - 'nop' => [ + 10 => [ 'title' => 'NOP', 'type' => 'text' ], - 'nama_pemilik_agunan' => [ + 11 => [ 'title' => 'Nama Pemilik Agunan', 'type' => 'text' ], - 'kode_sertifikat' => [ + 12 => [ 'title' => 'Kode Sertifikat', 'type' => 'text' ], - 'nomor_seri' => [ + 13 => [ 'title' => 'Nomor Seri', 'type' => 'text' ], - 'jumlah_pengikatan' => [ + 14 => [ 'title' => 'Jumlah Pengikatan', 'type' => 'number' ], - 'jenis_agunan' => [ + 15 => [ 'title' => 'Jenis Agunan', 'type' => 'text' ], - 'keterangan_objek' => [ + 16 => [ 'title' => 'Keterangan Objek', 'type' => 'text' ], - 'bukti_kepemilikan_objek' => [ + 17 => [ 'title' => 'Bukti Kepemilikan Objek', 'type' => 'text' ], - 'nilai_objek' => [ + 18 => [ 'title' => 'Nilai Objek', 'type' => 'number' ], - 'pemilik_agunan' => [ + 19 => [ 'title' => 'Pemilik Agunan', 'type' => 'text' ], - 'nilai_penjaminan' => [ + 20 => [ 'title' => 'Nilai Penjaminan', 'type' => 'number' ], - 'npwp' => [ + 21 => [ 'title' => 'NPWP', 'type' => 'text' ], - 'berkas_masuk' => [ + 22 => [ 'title' => 'Berkas Masuk', 'type' => 'text' ], - 'pewaris' => [ + 23 => [ 'title' => 'Pewaris', 'type' => 'text' ], - 'ahli_waris' => [ + 24 => [ 'title' => 'Ahli Waris', 'type' => 'text' ], - 'penerima_waris' => [ + 25 => [ 'title' => 'Penerima Waris', 'type' => 'text' ], - 'lokasi_tanah' => [ + 26 => [ 'title' => 'Lokasi Tanah', 'type' => 'text' ], - 'nilai_pajak' => [ + 27 => [ 'title' => 'Nilai Pajak', 'type' => 'number' ], - 'berkas_kembali' => [ + 28 => [ 'title' => 'Berkas Kembali', 'type' => 'text' ], - 'masuk_bpn' => [ + 29 => [ 'title' => 'Masuk BPN', 'type' => 'text' ], - 'tanggal_akad' => [ + 30 => [ 'title' => 'Tanggal Akad', 'type' => 'date' ], - 'nama_penjual' => [ + 31 => [ 'title' => 'Nama Penjual', 'type' => 'text' ], - 'nama_pembeli' => [ + 32 => [ 'title' => 'Nama Pembeli', 'type' => 'text' ], - 'sertifikat' => [ + 33 => [ 'title' => 'Sertifikat', 'type' => 'text' ], - 'nilai_jual_beli' => [ + 34 => [ 'title' => 'Nilai Jual Beli', 'type' => 'number' ], - 'nilai_ssb' => [ + 35 => [ 'title' => 'Nilai SSB', 'type' => 'number' ], - 'nilai_ssp' => [ + 36 => [ 'title' => 'Nilai SSP', 'type' => 'number' ], - 'keterangan_ppjb' => [ + 37 => [ 'title' => 'Keterangan PPJB', 'type' => 'text' ], - 'keterangan_kuasa_menjual' => [ + 38 => [ 'title' => 'Keterangan Kuasa Menjual', 'type' => 'text' ], - 'harga_real' => [ + 39 => [ 'title' => 'Harga Real', 'type' => 'number' ], - 'harga_kesepakatan' => [ + 40 => [ 'title' => 'Harga Kesepakatan', 'type' => 'number' ], - 'biaya' => [ + 41 => [ 'title' => 'Biaya', 'type' => 'number' ], - 'nama_direktur' => [ + 42 => [ 'title' => 'Nama Direktur', 'type' => 'text' ], - 'nama_komisaris' => [ + 43 => [ 'title' => 'Nama Komisaris', 'type' => 'text' ], - 'nama_pemilik_manfaat' => [ + 44 => [ 'title' => 'Nama Pemilik Manfaat', 'type' => 'text' ], - 'kedudukan_pt' => [ + 45 => [ 'title' => 'Kedudukan PT', 'type' => 'text' ], - 'nama_persero_aktif' => [ + 46 => [ 'title' => 'Nama Persero Aktif', 'type' => 'text' ], - 'nama_persero_pasib' => [ + 47 => [ 'title' => 'Nama Persero Pasif', 'type' => 'text' ], - 'nama_pembina' => [ + 48 => [ 'title' => 'Nama Pembina', 'type' => 'text' ], - 'nama_ketua' => [ + 49 => [ 'title' => 'Nama Ketua', 'type' => 'text' ], - 'nama_wakil' => [ + 50 => [ 'title' => 'Nama Wakil', 'type' => 'text' ], - 'nama_bendahara' => [ + 51 => [ 'title' => 'Nama Bendahara', 'type' => 'text' ], - 'tanggal_upload' => [ + 52 => [ 'title' => 'Tanggal Upload', 'type' => 'date' - ], + ] ]; User::factory()->create([ @@ -524,21 +514,34 @@ public function run(): void // Membuat 5 customer $customers = Customer::factory(35)->create(); - foreach ($products as $key => $product) { - Product::factory()->create([ - 'name' => $product['title'], - 'price' => rand(100000, 5000000), - 'description' => '', - 'data' => implode(',', $product['data']), + foreach ($datas as $id => $data) { + Data::factory()->create([ + 'id' => $id, + 'key' => $data['title'], + 'value' => $data['type'], + 'created_at' => now(), + 'updated_at' => now(), ]); } - foreach ($datas as $key => $val) { - Data::factory()->create([ - 'key' => $key, - 'value' => $val['title'], - 'type' => $val['type'] + // Insert data ke tabel 'products' dan 'data_product' + foreach ($products as $slug => $product) { + $productId = Product::factory()->create([ + 'name' => $product['title'], + 'price' => '0', + 'description' => '', + 'created_at' => now(), + 'updated_at' => now(), ]); + + foreach ($product['data'] as $dataId) { + DataProduct::factory()->create([ + 'data_id' => $dataId, + 'product_id' => $productId, + 'created_at' => now(), + 'updated_at' => now(), + ]); + } } foreach ($customers as $customer) { From 68d2c3f60ce8dcb756da7f006cb36e8f53da4e6c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 9 Jan 2025 11:02:44 +0700 Subject: [PATCH 065/184] Fix crud product --- app/Http/Controllers/DataController.php | 12 ++-- app/Http/Controllers/ProductController.php | 63 ++++++++++++++----- app/Models/Data.php | 2 +- ...025_01_08_224038_create_products_table.php | 2 +- .../2025_01_08_231951_create_data_table.php | 4 +- database/seeders/DatabaseSeeder.php | 8 +-- routes/api.php | 4 +- 7 files changed, 66 insertions(+), 29 deletions(-) diff --git a/app/Http/Controllers/DataController.php b/app/Http/Controllers/DataController.php index ffa081b..19113b5 100644 --- a/app/Http/Controllers/DataController.php +++ b/app/Http/Controllers/DataController.php @@ -3,23 +3,23 @@ namespace App\Http\Controllers; use App\Models\Data; -use App\Http\Requests\StoreDataRequest; -use App\Http\Requests\UpdateDataRequest; +use Illuminate\Http\Request; class DataController extends Controller { /** * Display a listing of the resource. */ - public function index() + public function index(Request $request) { - // + $data = Data::all(); + return response()->json($data); } /** * Store a newly created resource in storage. */ - public function store(StoreDataRequest $request) + public function store(Request $request) { // } @@ -35,7 +35,7 @@ public function show(Data $data) /** * Update the specified resource in storage. */ - public function update(UpdateDataRequest $request, Data $data) + public function update(Request $request, Data $data) { // } diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 22479a2..488b7dd 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -12,10 +12,23 @@ class ProductController extends Controller */ public function index(Request $request) { - // Mengambil produk dan memuat data terkait - $products = Product::with('dataProducts.data')->paginate(25); + $page = $request->query('page'); + $name = $request->query('name'); + + // Query dasar semua products + $query = Product::query(); + + // Filter berdasarkan name jika ada + if ($name && strlen($name) > 2) { + $query->where('name', 'like', '%' . $name . '%'); + } + + // shorting descending + $query->orderBy('created_at', 'desc'); + + // Paginate the results + $products = $query->paginate(25); - // Mengembalikan response dalam format JSON return response()->json($products); } @@ -25,13 +38,21 @@ public function index(Request $request) public function store(Request $request) { $request->validate([ - 'name' => 'required|string|max:255', - 'price' => 'required|string|max:255', - 'description' => 'required|string', - 'data' => 'required|string', + 'name' => 'string|max:255|nullable', + 'price' => 'numeric|nullable', + 'description' => 'string|nullable', + 'data_products' => 'array|nullable', ]); - $product = Product::create($request->all()); + $product = Product::create($request->only('name', 'price', 'description')); + + // Simpan data_products + if ($request->has('data_products')) { + foreach ($request->input('data_products') as $dataId) { + $product->dataProducts()->create(['data_id' => $dataId]); + } + } + return response()->json($product, 201); } @@ -50,14 +71,24 @@ public function show($id) public function update(Request $request, $id) { $request->validate([ - 'name' => 'string|max:255', - 'price' => 'string|max:255', - 'description' => 'string', - 'data' => 'string', + 'name' => 'string|max:255|nullable', + 'price' => 'numeric|nullable', + 'description' => 'string|nullable', + 'data_products' => 'array|nullable', ]); - $product = Product::findOrFail($id); - $product->update($request->all()); + $product = Product::with('dataProducts.data')->findOrFail($id); + + $product->update($request->only('name', 'price', 'description')); + + // Update data_products + if ($request->has('data_products')) { + $product->dataProducts()->delete(); + foreach ($request->input('data_products') as $dataId) { + $product->dataProducts()->create(['data_id' => $dataId]); + } + } + return response()->json($product); } @@ -68,6 +99,10 @@ public function destroy($id) { $product = Product::findOrFail($id); $product->delete(); + + // hapus data_products + $product->dataProducts()->delete(); + return response()->json(null, 204); } } diff --git a/app/Models/Data.php b/app/Models/Data.php index 393ab9b..d117149 100644 --- a/app/Models/Data.php +++ b/app/Models/Data.php @@ -13,7 +13,7 @@ class Data extends Model protected $table = 'data'; protected $fillable = [ - 'key', + 'name', 'value', 'type' ]; diff --git a/database/migrations/2025_01_08_224038_create_products_table.php b/database/migrations/2025_01_08_224038_create_products_table.php index b466eaa..58c75c6 100644 --- a/database/migrations/2025_01_08_224038_create_products_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -15,7 +15,7 @@ public function up(): void $table->id(); $table->string('name'); $table->string('price'); - $table->text('description'); + $table->text('description')->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2025_01_08_231951_create_data_table.php b/database/migrations/2025_01_08_231951_create_data_table.php index 974e5a9..b8724eb 100644 --- a/database/migrations/2025_01_08_231951_create_data_table.php +++ b/database/migrations/2025_01_08_231951_create_data_table.php @@ -13,8 +13,8 @@ public function up(): void { Schema::create('data', function (Blueprint $table) { $table->id(); - $table->string('key'); - $table->string('value'); + $table->string('name'); + $table->string('type'); $table->timestamps(); }); } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index bfa409a..5184bb2 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -517,8 +517,8 @@ public function run(): void foreach ($datas as $id => $data) { Data::factory()->create([ 'id' => $id, - 'key' => $data['title'], - 'value' => $data['type'], + 'name' => $data['title'], + 'type' => $data['type'], 'created_at' => now(), 'updated_at' => now(), ]); @@ -528,8 +528,8 @@ public function run(): void foreach ($products as $slug => $product) { $productId = Product::factory()->create([ 'name' => $product['title'], - 'price' => '0', - 'description' => '', + 'price' => '500000', + 'description' => '-', 'created_at' => now(), 'updated_at' => now(), ]); diff --git a/routes/api.php b/routes/api.php index 2217026..1233f6a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -10,6 +10,7 @@ use App\Http\Controllers\SettingController; use App\Http\Controllers\UserController; use App\Http\Controllers\ProductController; +use App\Http\Controllers\DataController; use App\Http\Controllers\Auth\ProfileController; Route::middleware(['auth:sanctum'])->group(function () { @@ -26,6 +27,7 @@ 'jobdesks' => JobdeskController::class, 'customers' => CustomerController::class, 'settings' => SettingController::class, - 'products' => ProductController::class + 'products' => ProductController::class, + 'data' => DataController::class ]); }); From b11e90330dc693603db8f33d79fb6f9091c50bdd Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 9 Jan 2025 15:41:03 +0700 Subject: [PATCH 066/184] change structure table --- app/Http/Controllers/OrderController.php | 6 +++--- app/Http/Controllers/ProductController.php | 9 ++++++++- app/Models/Order.php | 11 ++++++++--- app/Models/Product.php | 5 +++++ database/factories/DataFactory.php | 3 ++- database/factories/OrderFactory.php | 16 ++++++---------- .../2024_11_06_033508_create_orders_table.php | 4 ++-- 7 files changed, 34 insertions(+), 20 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index a620bf4..26b3fe8 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -11,11 +11,11 @@ class OrderController extends Controller private $validate = [ 'order_date' => 'required', - 'service' => 'required', + 'product_id' => 'required', 'price' => 'required', 'paid' => 'required', 'payment_method' => 'required', - 'document' => 'required', + 'data' => 'required', 'customer_id' => 'required|exists:customers,id', ]; public function index(Request $request) @@ -26,7 +26,7 @@ public function index(Request $request) $status = $request->query('status'); $status = isset($status) ? $status : null; - $query = Order::with('customer', 'jobdesks'); + $query = Order::with('customer', 'jobdesks', 'product'); if ($customerId) { $query->where('customer_id', $customerId); diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 488b7dd..4c8507a 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -18,6 +18,8 @@ public function index(Request $request) // Query dasar semua products $query = Product::query(); + $query->with('dataProducts.data'); + // Filter berdasarkan name jika ada if ($name && strlen($name) > 2) { $query->where('name', 'like', '%' . $name . '%'); @@ -27,7 +29,12 @@ public function index(Request $request) $query->orderBy('created_at', 'desc'); // Paginate the results - $products = $query->paginate(25); + if ($page === 'all') { + $products = $query->get(); + } else { + $products = $query->paginate(25); + } + return response()->json($products); } diff --git a/app/Models/Order.php b/app/Models/Order.php index 8e22c22..0c53099 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -12,16 +12,16 @@ class Order extends Model protected $fillable = [ 'customer_id', 'order_date', - 'service', + 'product_id', 'price', 'payment_method', 'paid', - 'document', + 'data', 'lampiran', ]; protected $casts = [ - 'document' => 'array', + 'data' => 'array', ]; public function customer() @@ -29,6 +29,11 @@ public function customer() return $this->belongsTo(Customer::class); } + public function product() + { + return $this->belongsTo(Product::class); + } + public function jobdesks() { return $this->hasMany(Jobdesk::class); diff --git a/app/Models/Product.php b/app/Models/Product.php index 27e339c..04ebb89 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -20,4 +20,9 @@ public function dataProducts() { return $this->hasMany(DataProduct::class, 'product_id'); } + + public function order() + { + return $this->belongsTo(Order::class); + } } diff --git a/database/factories/DataFactory.php b/database/factories/DataFactory.php index e181de8..fd100ad 100644 --- a/database/factories/DataFactory.php +++ b/database/factories/DataFactory.php @@ -17,7 +17,8 @@ class DataFactory extends Factory public function definition(): array { return [ - // + 'name' => $this->faker->name(), + 'type' => $this->faker->word(), ]; } } diff --git a/database/factories/OrderFactory.php b/database/factories/OrderFactory.php index b2dfebe..fc28ade 100644 --- a/database/factories/OrderFactory.php +++ b/database/factories/OrderFactory.php @@ -16,25 +16,21 @@ class OrderFactory extends Factory */ public function definition(): array { - $layanan_notaris = [ - 'Pembuatan Akta Otentik', - 'Pembuatan Wasiat', - 'Pengesahan Dokumen', - 'Peralihan Hak Tanah', - 'Pembuatan Surat Kuasa', - 'Jasa Legalitas' - ]; $price = fake()->numberBetween(1000000, 10000000); $paid = fake()->numberBetween(1000000, $price); $order_date = fake()->dateTimeBetween('-6 months', 'now'); return [ 'customer_id' => fake()->numberBetween(1, 10), 'order_date' => $order_date, - 'service' => fake()->randomElement($layanan_notaris), + 'product_id' => fake()->numberBetween(1, 10), 'price' => $price, 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), 'paid' => $paid, - 'document' => ['KTP', 'PBB', 'KK'] + 'data' => [ + 'ktp' => fake()->numberBetween(1, 10), + 'kk' => fake()->numberBetween(1, 10), + 'npwp' => fake()->numberBetween(1, 10), + ] ]; } } diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php index cefdc89..cf27a87 100644 --- a/database/migrations/2024_11_06_033508_create_orders_table.php +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -15,11 +15,11 @@ public function up(): void $table->id(); $table->string('customer_id'); $table->date('order_date'); - $table->string('service'); + $table->string('product_id'); $table->integer('price')->nullable(); $table->string('payment_method')->nullable(); $table->integer('paid')->nullable(); - $table->text('document')->nullable(); + $table->text('data')->nullable(); $table->text('lampiran')->nullable(); $table->timestamps(); }); From 54121c9ba286d9718d2fa8a605d42c556ba42948 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 10 Jan 2025 09:08:42 +0700 Subject: [PATCH 067/184] update seeder --- database/seeders/DatabaseSeeder.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 5184bb2..092bfef 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -91,8 +91,6 @@ public function run(): void 36, // Nilai SSP 37, // Keterangan PPJB 38, // Keterangan Kuasa Menjual - 39, // Harga Real - 40, // Harga Kesepakatan ], ], 'hibah' => [ @@ -109,8 +107,6 @@ public function run(): void 36, // Nilai SSP 37, // Keterangan PPJB 38, // Keterangan Kuasa Menjual - 39, // Harga Real - 40, // Harga Kesepakatan ], ], 'turun_waris' => [ From f71165c3b05a14c7d0d4db03ebc6c1312049b15d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 10 Jan 2025 15:39:53 +0700 Subject: [PATCH 068/184] data product --- app/Models/Product.php | 1 + database/factories/DataFactory.php | 2 + database/factories/DataProductFactory.php | 6 +- database/factories/ProductFactory.php | 3 + ...025_01_08_224038_create_products_table.php | 1 + database/seeders/DatabaseSeeder.php | 262 +++++------------- 6 files changed, 83 insertions(+), 192 deletions(-) diff --git a/app/Models/Product.php b/app/Models/Product.php index 04ebb89..d485dd3 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -13,6 +13,7 @@ class Product extends Model 'name', 'price', 'description', + 'category', 'data', ]; diff --git a/database/factories/DataFactory.php b/database/factories/DataFactory.php index fd100ad..0eb5c0c 100644 --- a/database/factories/DataFactory.php +++ b/database/factories/DataFactory.php @@ -19,6 +19,8 @@ public function definition(): array return [ 'name' => $this->faker->name(), 'type' => $this->faker->word(), + 'created_at' => now(), + 'updated_at' => now(), ]; } } diff --git a/database/factories/DataProductFactory.php b/database/factories/DataProductFactory.php index 770a36f..53c6bf4 100644 --- a/database/factories/DataProductFactory.php +++ b/database/factories/DataProductFactory.php @@ -24,8 +24,10 @@ class DataProductFactory extends Factory public function definition() { return [ - 'data_id' => Data::factory(), // Create or use an existing Data model - 'product_id' => Product::factory(), // Create or use an existing Product model + 'data_id' => Data::factory(), + 'product_id' => Product::factory(), + 'created_at' => now(), + 'updated_at' => now(), ]; } } diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php index 7ceacea..8fed164 100644 --- a/database/factories/ProductFactory.php +++ b/database/factories/ProductFactory.php @@ -14,7 +14,10 @@ public function definition() return [ 'name' => $this->faker->word, 'price' => $this->faker->randomFloat(0, 500000, 5000000), + 'category' => $this->faker->randomElement(['bank', 'perorangan']), 'description' => $this->faker->paragraph, + 'created_at' => now(), + 'updated_at' => now(), ]; } } diff --git a/database/migrations/2025_01_08_224038_create_products_table.php b/database/migrations/2025_01_08_224038_create_products_table.php index 58c75c6..a1f6b06 100644 --- a/database/migrations/2025_01_08_224038_create_products_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -15,6 +15,7 @@ public function up(): void $table->id(); $table->string('name'); $table->string('price'); + $table->string('category'); $table->text('description')->nullable(); $table->timestamps(); }); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 092bfef..25083e6 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -24,233 +24,120 @@ public function run(): void $products = [ 'perjanjian_kredit' => [ 'title' => 'Perjanjian Kredit', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 4, // Yang Mengerjakan - 5, // Jumlah Pinjaman - 6, // Lain-lain - ], + 'data' => [1, 2, 3, 4, 5, 6], + 'category' => 'perorangan' ], 'skmht' => [ 'title' => 'SKMHT', - 'data' => [ - 2, // Nomor Akta - 3, // Tanggal Akta - 8, // Nomor Agunan - 9, // NIB - 10, // NOP - 11, // Nama Pemilik Agunan - 12, // Kode Sertifikat - 13, // Nomor Seri - 14, // Jumlah Pengikatan - 7, // Tanggal Habis SKMHT - ], + 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14, 7], + 'category' => 'perorangan' ], 'apht' => [ 'title' => 'APHT', - 'data' => [ - 2, // Nomor Akta - 3, // Tanggal Akta - 8, // Nomor Agunan - 9, // NIB - 10, // NOP - 11, // Nama Pemilik Agunan - 12, // Kode Sertifikat - 13, // Nomor Seri - 14, // Jumlah Pengikatan - ], + 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14], + 'category' => 'perorangan' ], 'fidusia' => [ 'title' => 'Fidusia', - 'data' => [ - 2, // Nomor Akta - 3, // Tanggal Akta - 15, // Jenis Agunan - 16, // Keterangan Objek - 17, // Bukti Kepemilikan Objek - 18, // Nilai Objek - 19, // Pemilik Agunan - 20, // Nilai Penjaminan - 21, // NPWP - 7, // Tanggal Habis SKMHT - ], + 'data' => [2, 3, 15, 16, 17, 18, 19, 20, 21, 7], + 'category' => 'perorangan' ], 'jual_beli' => [ 'title' => 'Jual Beli', - 'data' => [ - 2, // Nomor Akta - 3, // Tanggal Akta - 31, // Nama Penjual - 32, // Nama Pembeli - 33, // Sertifikat - 26, // Lokasi Tanah - 34, // Nilai Jual Beli - 35, // Nilai SSB - 36, // Nilai SSP - 37, // Keterangan PPJB - 38, // Keterangan Kuasa Menjual - ], + 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'category' => 'perorangan', ], 'hibah' => [ 'title' => 'Hibah', - 'data' => [ - 2, // Nomor Akta - 3, // Tanggal Akta - 31, // Nama Penjual - 32, // Nama Pembeli - 33, // Sertifikat - 26, // Lokasi Tanah - 34, // Nilai Jual Beli - 35, // Nilai SSB - 36, // Nilai SSP - 37, // Keterangan PPJB - 38, // Keterangan Kuasa Menjual - ], + 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'category' => 'perorangan', ], 'turun_waris' => [ 'title' => 'Turun Waris', - 'data' => [ - 22, // Berkas Masuk - 23, // Pewaris - 24, // Ahli Waris - 25, // Penerima Waris - 26, // Lokasi Tanah - 27, // Nilai Pajak - 28, // Berkas Kembali - 29, // Masuk BPN - 30, // Tanggal Akad - ], + 'data' => [22, 23, 24, 25, 26, 27, 28, 29, 30], + 'category' => 'perorangan', ], 'pecah' => [ 'title' => 'Pecah', - 'data' => [ - 1, // Judul Akta - 44, // Nama Pemilik Sertifikat - // Tambahkan elemen lain yang sesuai jika perlu - ], + 'data' => [1, 44], + 'category' => 'perorangan', ], 'pendirian_pt' => [ 'title' => 'Pendirian PT', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 42, // Nama Direktur - 43, // Nama Komisaris - 21, // NPWP Direktur - 21, // NPWP Komisaris - 44, // Nama Pemilik Manfaat - 45, // Kedudukan PT - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 42, 43, 21, 21, 44, 45, 41, 52], + 'category' => 'perorangan', ], 'pendirian_cv' => [ 'title' => 'Pendirian CV', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 46, // Nama Persero Aktif - 47, // Nama Persero Pasif - 21, // NPWP Persero Aktif - 21, // NPWP Persero Pasif - 45, // Kedudukan PT - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 46, 47, 21, 21, 45, 41, 52], + 'category' => 'perorangan', ], 'pendirian_yayasan' => [ 'title' => 'Pendirian Yayasan', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 48, // Nama Pembina - 49, // Nama Ketua - 50, // Nama Wakil - 51, // Nama Bendahara - 6, // Lain-lain - 21, // NPWP Yayasan - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'category' => 'perorangan', ], 'pendirian_pt_perseorangan' => [ 'title' => 'Pendirian PT Perseorangan', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 42, // Nama Direktur - 21, // NPWP Direktur - 45, // Kedudukan PT - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 42, 21, 45, 41, 52], + 'category' => 'perorangan', ], 'perubahan_pt' => [ 'title' => 'Perubahan PT', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 42, // Nama Direktur - 43, // Nama Komisaris - 21, // NPWP Direktur - 21, // NPWP Komisaris - 44, // Nama Pemilik Manfaat - 45, // Kedudukan PT - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 42, 43, 21, 21, 44, 45, 41, 52], + 'category' => 'perorangan', ], 'perubahan_cv' => [ 'title' => 'Perubahan CV', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 46, // Nama Persero Aktif - 47, // Nama Persero Pasif - 21, // NPWP Persero Aktif - 21, // NPWP Persero Pasif - 45, // Kedudukan PT - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 46, 47, 21, 21, 45, 41, 52], + 'category' => 'perorangan', ], 'perubahan_yayasan' => [ 'title' => 'Perubahan Yayasan', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 48, // Nama Pembina - 49, // Nama Ketua - 50, // Nama Wakil - 51, // Nama Bendahara - 6, // Lain-lain - 21, // NPWP Yayasan - 41, // Biaya - 52, // Tanggal Upload - ], + 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'category' => 'perorangan', ], 'perubahan_pt_perseorangan' => [ 'title' => 'Perubahan PT Perseorangan', - 'data' => [ - 1, // Judul Akta - 2, // Nomor Akta - 3, // Tanggal Akta - 42, // Nama Direktur - 21, // NPWP Direktur - 45, // Kedudukan PT - 41, // Biaya - 52, // Tanggal Upload - ], - ], + 'data' => [1, 2, 3, 42, 21, 45, 41, 52], + 'category' => 'perorangan', + ], + // BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat' + 'bpr_bba' => [ + 'title' => 'BPR BBA', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_pala_pusat' => [ + 'title' => 'BPR Pala Pusat', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_pala_cabang' => [ + 'title' => 'BPR Pala Cabang', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_danamas_prime' => [ + 'title' => 'BPR Danamas Prime', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_arum_mandiri' => [ + 'title' => 'BPR Arum Mandiri', + 'data' => [], + 'category' => 'bank', + ], + 'bprs_madina_mandiri' => [ + 'title' => 'BPRS Madina Mandiri', + 'data' => [], + 'category' => 'bank', + ], + 'bmt_sejahtera_ummat' => [ + 'title' => 'BMT Sejahtera Ummat', + 'data' => [], + 'category' => 'bank', + ] ]; $datas = [ 1 => [ @@ -514,9 +401,7 @@ public function run(): void Data::factory()->create([ 'id' => $id, 'name' => $data['title'], - 'type' => $data['type'], - 'created_at' => now(), - 'updated_at' => now(), + 'type' => $data['type'] ]); } @@ -526,16 +411,13 @@ public function run(): void 'name' => $product['title'], 'price' => '500000', 'description' => '-', - 'created_at' => now(), - 'updated_at' => now(), + 'category' => $product['category'] ]); foreach ($product['data'] as $dataId) { DataProduct::factory()->create([ 'data_id' => $dataId, - 'product_id' => $productId, - 'created_at' => now(), - 'updated_at' => now(), + 'product_id' => $productId ]); } } From b09e480d61fd68707f07d70807dac04479444ca3 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 11 Jan 2025 13:40:42 +0700 Subject: [PATCH 069/184] add relation order --- app/Http/Controllers/JobdeskController.php | 2 +- app/Http/Controllers/OrderController.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 7a16fb2..e8eef40 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -15,7 +15,7 @@ public function index(Request $request) $user_id = $request->query('user_id'); // Initialize the query - $query = Jobdesk::with('customer', 'order', 'user'); + $query = Jobdesk::with('customer', 'order', 'user', 'order.product'); // Filter by order_id if provided if ($orderId) { diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 26b3fe8..907b320 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -26,7 +26,7 @@ public function index(Request $request) $status = $request->query('status'); $status = isset($status) ? $status : null; - $query = Order::with('customer', 'jobdesks', 'product'); + $query = Order::with('customer', 'jobdesks', 'product', 'product.dataProducts.data'); if ($customerId) { $query->where('customer_id', $customerId); From 271a7326cefaf85736c0602ba7d9c76739308497 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 12 Jan 2025 22:31:47 +0700 Subject: [PATCH 070/184] rename pagination --- app/Http/Controllers/KaryawanController.php | 13 ++++++++++--- app/Http/Controllers/OrderController.php | 11 +++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index ce6f78c..3afcb37 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -16,7 +16,7 @@ class KaryawanController extends Controller public function index(Request $request) { - $page = $request->query('page'); + $paginanate = $request->query('paginanate'); $name = $request->query('name'); // Query dasar semua user @@ -29,8 +29,15 @@ public function index(Request $request) // shorting descending $query->orderBy('created_at', 'desc'); - // Paginate the results - $users = $query->paginate(25); + // Check if pagination should be disabled + if ($paginanate === 'false') { + // Get all records without pagination + $users = $query->get(); + } else { + // Paginate results + $users = $query->paginate(25); + } + return response()->json($users); } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 907b320..e52b1fb 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -20,8 +20,8 @@ class OrderController extends Controller ]; public function index(Request $request) { - $customerId = $request->query('customer_id'); + $paginanate = $request->query('paginanate'); $name = $request->query('name'); $status = $request->query('status'); $status = isset($status) ? $status : null; @@ -57,7 +57,14 @@ public function index(Request $request) $query->orderBy('created_at', 'desc'); - $orders = $query->paginate(25); + // Check if pagination should be disabled + if ($paginanate === 'false') { + // Get all records without pagination + $orders = $query->get(); + } else { + // Paginate results + $orders = $query->paginate(25); + } return response()->json($orders); } From e6a1fc61dc0c9af3b1798810a0eaa326ff782736 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 16 Jan 2025 15:35:46 +0700 Subject: [PATCH 071/184] add notif --- .../Controllers/NotificationController.php | 163 ++++++++++++++++++ app/Http/Controllers/SettingController.php | 144 +++++++--------- 2 files changed, 222 insertions(+), 85 deletions(-) create mode 100644 app/Http/Controllers/NotificationController.php diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php new file mode 100644 index 0000000..0d90c3c --- /dev/null +++ b/app/Http/Controllers/NotificationController.php @@ -0,0 +1,163 @@ +get('setting_key'); + $settings = Setting::all(); + + $datas = []; + foreach ($settings as $setting) { + $datas[$setting->setting_key] = $setting->setting_value; + } + + if ($setting_key && isset($datas[$setting_key])) { + return response()->json([$setting_key => $datas[$setting_key]]); + } + + return response()->json($datas); + } + + /** + * Store or update settings in storage. + */ + public function store(Request $request) + { + // Define validation rules + $validatedData = $request->validate([ + 'app_name' => 'nullable|string|max:255', + 'app_description' => 'nullable|string|max:500', + 'alamat' => 'nullable|string|max:255', + 'banks' => 'nullable|string|max:2000', + 'pekerjaan' => 'nullable|string|max:10000', + 'pdf_sample' => 'nullable', + 'email' => 'nullable|email|max:255', + ]); + + if (is_string($request->pdf_sample)) { + unset($validatedData['pdf_sample']); + } + $settingsToSave = []; + + if ($request->hasFile('pdf_sample')) { + $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); + $settingsToSave['pdf_sample'] = $pdfPath; + } + + // Save or update each setting + foreach ($validatedData as $key => $value) { + $settingsToSave[$key] = $value; // Add other validated settings + Setting::updateOrCreate( + ['setting_key' => $key], + ['setting_value' => $value] + ); + } + + return response()->json([ + 'success' => true, + 'message' => 'Settings saved successfully.', + 'data' => $settingsToSave + ], 201); + } + + /** + * Display the specified setting. + */ + public function show($key) + { + $setting = Setting::where('setting_key', $key)->first(); + + if (!$setting) { + return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); + } + + return response()->json($setting); + } + + /** + * Update the specified setting in storage. + */ + public function update(Request $request, $key) + { + $setting = Setting::where('setting_key', $key)->first(); + + if (!$setting) { + return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); + } + + // Define validation rules + $validatedData = $request->validate([ + 'app_name' => 'nullable|string|max:255', + 'app_description' => 'nullable|string|max:500', + 'alamat' => 'nullable|string|max:255', + 'banks' => 'nullable|string|max:2000', + 'pekerjaan' => 'nullable|string|max:2000', + 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', + 'email' => 'nullable|email|max:255', + ]); + + if (is_string($request->pdf_sample)) { + unset($validatedData['pdf_sample']); + } + + $settingsToUpdate = []; + + if ($request->hasFile('pdf_sample')) { + if ($setting->setting_key === 'pdf_sample') { + Storage::disk('public')->delete($setting->setting_value); + } + $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); + $settingsToUpdate['pdf_sample'] = $pdfPath; + } + + // Update the setting value + foreach ($validatedData as $key => $value) { + $settingsToUpdate[$key] = $value; + $setting->update(['setting_value' => $value]); + } + + return response()->json([ + 'success' => true, + 'message' => 'Setting updated successfully.', + 'data' => $setting + ], 200); + } + + /** + * Remove the specified setting from storage. + */ + public function destroy($key) + { + $setting = Setting::where('setting_key', $key)->first(); + + if (!$setting) { + return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); + } + + // Delete associated file if exists + if ($setting->setting_value) { + Storage::disk('public')->delete($setting->setting_value); + } + + // Delete the setting record + $setting->delete(); + + return response()->json([ + 'success' => true, + 'message' => 'Setting deleted successfully.' + ], 200); + } +} diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 88ff062..f0c01e1 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -16,19 +16,13 @@ class SettingController extends Controller */ public function index(Request $request) { - $setting_key = $request->get('setting_key'); - $settings = Setting::all(); + $settings = Setting::all()->pluck('setting_value', 'setting_key')->toArray(); - $datas = []; - foreach ($settings as $setting) { - $datas[$setting->setting_key] = $setting->setting_value; // Gunakan 'setting_key' dari objek setting + if ($settingKey = $request->get('setting_key')) { + return response()->json([$settingKey => $settings[$settingKey] ?? null]); } - if ($setting_key && isset($datas[$setting_key])) { - return response()->json([$setting_key => $datas[$setting_key]]); - } - - return response()->json($datas); + return response()->json($settings); } /** @@ -37,40 +31,17 @@ public function index(Request $request) public function store(Request $request) { // Define validation rules - $validatedData = $request->validate([ - 'app_name' => 'nullable|string|max:255', - 'app_description' => 'nullable|string|max:500', - 'alamat' => 'nullable|string|max:255', - 'banks' => 'nullable|string|max:2000', - 'pekerjaan' => 'nullable|string|max:10000', - 'pdf_sample' => 'nullable', - 'email' => 'nullable|email|max:255', - ]); - - if (is_string($request->pdf_sample)) { - unset($validatedData['pdf_sample']); - } - $settingsToSave = []; + $validatedData = $request->validate($this->validationRules()); + // Handle file upload if exists if ($request->hasFile('pdf_sample')) { - $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); - $settingsToSave['pdf_sample'] = $pdfPath; + $validatedData['pdf_sample'] = $request->file('pdf_sample')->store('pdf_samples', 'public'); } - // Save or update each setting - foreach ($validatedData as $key => $value) { - $settingsToSave[$key] = $value; // Add other validated settings - Setting::updateOrCreate( - ['setting_key' => $key], - ['setting_value' => $value] - ); - } + // Save or update settings + $this->saveSettings($validatedData); - return response()->json([ - 'success' => true, - 'message' => 'Settings saved successfully.', - 'data' => $settingsToSave - ], 201); + return $this->responseSuccess('Settings saved successfully.', $validatedData); } /** @@ -78,11 +49,7 @@ public function store(Request $request) */ public function show($key) { - $setting = Setting::where('setting_key', $key)->first(); - - if (!$setting) { - return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); - } + $setting = Setting::where('setting_key', $key)->firstOrFail(); return response()->json($setting); } @@ -92,48 +59,21 @@ public function show($key) */ public function update(Request $request, $key) { - $setting = Setting::where('setting_key', $key)->first(); - - if (!$setting) { - return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); - } + $setting = Setting::where('setting_key', $key)->firstOrFail(); // Define validation rules - $validatedData = $request->validate([ - 'app_name' => 'nullable|string|max:255', - 'app_description' => 'nullable|string|max:500', - 'alamat' => 'nullable|string|max:255', - 'banks' => 'nullable|string|max:2000', - 'pekerjaan' => 'nullable|string|max:2000', - 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', - 'email' => 'nullable|email|max:255', - ]); - - if (is_string($request->pdf_sample)) { - unset($validatedData['pdf_sample']); - } - - $settingsToUpdate = []; + $validatedData = $request->validate($this->validationRules()); + // Handle file upload and delete previous file if necessary if ($request->hasFile('pdf_sample')) { - if ($setting->setting_key === 'pdf_sample') { - Storage::disk('public')->delete($setting->setting_value); - } - $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); - $settingsToUpdate['pdf_sample'] = $pdfPath; + Storage::disk('public')->delete($setting->setting_value); + $validatedData['pdf_sample'] = $request->file('pdf_sample')->store('pdf_samples', 'public'); } - // Update the setting value - foreach ($validatedData as $key => $value) { - $settingsToUpdate[$key] = $value; - $setting->update(['setting_value' => $value]); - } + // Update the setting + $setting->update($validatedData); - return response()->json([ - 'success' => true, - 'message' => 'Setting updated successfully.', - 'data' => $setting - ], 200); + return $this->responseSuccess('Setting updated successfully.', $setting); } /** @@ -141,11 +81,7 @@ public function update(Request $request, $key) */ public function destroy($key) { - $setting = Setting::where('setting_key', $key)->first(); - - if (!$setting) { - return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); - } + $setting = Setting::where('setting_key', $key)->firstOrFail(); // Delete associated file if exists if ($setting->setting_value) { @@ -155,9 +91,47 @@ public function destroy($key) // Delete the setting record $setting->delete(); + return $this->responseSuccess('Setting deleted successfully.'); + } + + /** + * Validation rules for storing/updating settings. + */ + protected function validationRules() + { + return [ + 'app_name' => 'nullable|string|max:255', + 'app_description' => 'nullable|string|max:500', + 'alamat' => 'nullable|string|max:255', + 'banks' => 'nullable|string|max:2000', + 'pekerjaan' => 'nullable|string|max:10000', + 'pdf_sample' => 'nullable', + 'email' => 'nullable|email|max:255', + ]; + } + + /** + * Save settings to the database. + */ + protected function saveSettings(array $settings) + { + foreach ($settings as $key => $value) { + Setting::updateOrCreate( + ['setting_key' => $key], + ['setting_value' => $value] + ); + } + } + + /** + * Create a success response. + */ + protected function responseSuccess(string $message, $data = null) + { return response()->json([ 'success' => true, - 'message' => 'Setting deleted successfully.' + 'message' => $message, + 'data' => $data ], 200); } } From 5aa37b35cf4d4f10cfd9f2a39eba80ec9e71461a Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 17 Jan 2025 11:14:27 +0700 Subject: [PATCH 072/184] fix crud notification template --- .../Controllers/NotificationController.php | 163 ------------------ app/Http/Controllers/SettingController.php | 3 + ...2_17_145546_create_notifications_table.php | 2 +- database/seeders/DatabaseSeeder.php | 62 ++++++- 4 files changed, 63 insertions(+), 167 deletions(-) delete mode 100644 app/Http/Controllers/NotificationController.php diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php deleted file mode 100644 index 0d90c3c..0000000 --- a/app/Http/Controllers/NotificationController.php +++ /dev/null @@ -1,163 +0,0 @@ -get('setting_key'); - $settings = Setting::all(); - - $datas = []; - foreach ($settings as $setting) { - $datas[$setting->setting_key] = $setting->setting_value; - } - - if ($setting_key && isset($datas[$setting_key])) { - return response()->json([$setting_key => $datas[$setting_key]]); - } - - return response()->json($datas); - } - - /** - * Store or update settings in storage. - */ - public function store(Request $request) - { - // Define validation rules - $validatedData = $request->validate([ - 'app_name' => 'nullable|string|max:255', - 'app_description' => 'nullable|string|max:500', - 'alamat' => 'nullable|string|max:255', - 'banks' => 'nullable|string|max:2000', - 'pekerjaan' => 'nullable|string|max:10000', - 'pdf_sample' => 'nullable', - 'email' => 'nullable|email|max:255', - ]); - - if (is_string($request->pdf_sample)) { - unset($validatedData['pdf_sample']); - } - $settingsToSave = []; - - if ($request->hasFile('pdf_sample')) { - $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); - $settingsToSave['pdf_sample'] = $pdfPath; - } - - // Save or update each setting - foreach ($validatedData as $key => $value) { - $settingsToSave[$key] = $value; // Add other validated settings - Setting::updateOrCreate( - ['setting_key' => $key], - ['setting_value' => $value] - ); - } - - return response()->json([ - 'success' => true, - 'message' => 'Settings saved successfully.', - 'data' => $settingsToSave - ], 201); - } - - /** - * Display the specified setting. - */ - public function show($key) - { - $setting = Setting::where('setting_key', $key)->first(); - - if (!$setting) { - return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); - } - - return response()->json($setting); - } - - /** - * Update the specified setting in storage. - */ - public function update(Request $request, $key) - { - $setting = Setting::where('setting_key', $key)->first(); - - if (!$setting) { - return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); - } - - // Define validation rules - $validatedData = $request->validate([ - 'app_name' => 'nullable|string|max:255', - 'app_description' => 'nullable|string|max:500', - 'alamat' => 'nullable|string|max:255', - 'banks' => 'nullable|string|max:2000', - 'pekerjaan' => 'nullable|string|max:2000', - 'pdf_sample' => 'nullable|file|mimes:pdf|max:2048', - 'email' => 'nullable|email|max:255', - ]); - - if (is_string($request->pdf_sample)) { - unset($validatedData['pdf_sample']); - } - - $settingsToUpdate = []; - - if ($request->hasFile('pdf_sample')) { - if ($setting->setting_key === 'pdf_sample') { - Storage::disk('public')->delete($setting->setting_value); - } - $pdfPath = $request->file('pdf_sample')->store('pdf_samples', 'public'); - $settingsToUpdate['pdf_sample'] = $pdfPath; - } - - // Update the setting value - foreach ($validatedData as $key => $value) { - $settingsToUpdate[$key] = $value; - $setting->update(['setting_value' => $value]); - } - - return response()->json([ - 'success' => true, - 'message' => 'Setting updated successfully.', - 'data' => $setting - ], 200); - } - - /** - * Remove the specified setting from storage. - */ - public function destroy($key) - { - $setting = Setting::where('setting_key', $key)->first(); - - if (!$setting) { - return response()->json(['success' => false, 'message' => 'Setting not found.'], 404); - } - - // Delete associated file if exists - if ($setting->setting_value) { - Storage::disk('public')->delete($setting->setting_value); - } - - // Delete the setting record - $setting->delete(); - - return response()->json([ - 'success' => true, - 'message' => 'Setting deleted successfully.' - ], 200); - } -} diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index f0c01e1..2bf5733 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -107,6 +107,9 @@ protected function validationRules() 'pekerjaan' => 'nullable|string|max:10000', 'pdf_sample' => 'nullable', 'email' => 'nullable|email|max:255', + 'new_order' => 'nullable|string', + 'project_assignment' => 'nullable|string', + 'followup_project' => 'nullable|string', ]; } diff --git a/database/migrations/2024_12_17_145546_create_notifications_table.php b/database/migrations/2024_12_17_145546_create_notifications_table.php index 002c80d..e76414c 100644 --- a/database/migrations/2024_12_17_145546_create_notifications_table.php +++ b/database/migrations/2024_12_17_145546_create_notifications_table.php @@ -14,7 +14,7 @@ public function up(): void Schema::create('notifications', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('type'); - $table->string('notifiable_type', 191); // Set length for notifiable_type + $table->string('notifiable_type', 191); $table->text('data'); $table->timestamp('read_at')->nullable(); $table->timestamps(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 25083e6..8e5d76d 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -409,7 +409,6 @@ public function run(): void foreach ($products as $slug => $product) { $productId = Product::factory()->create([ 'name' => $product['title'], - 'price' => '500000', 'description' => '-', 'category' => $product['category'] ]); @@ -437,8 +436,65 @@ public function run(): void } } - Setting::create(['setting_key' => 'app_name', 'setting_value' => 'NOTANUXT']); - Setting::create(['setting_key' => 'app_description', 'setting_value' => 'NOTANUXT | Asisten Notaris Online']); + $template_order = ' + Pemberitahuan Order Layanan Notaris Baru
+
+ Tanggal: [tanggal_order]
+
+ Detail Order:
+ ======================================
+ Nama Klien: [Nama Klien]
+ Nomor Telepon: [no_telp]
+ Email: [email]
+ Jenis Layanan Notaris: [product]
+ ======================================
+
+ Harap segera follow up order ini ke staff terkait.
+
+ Terima kasih.
+ [tim_manajemen] + '; + $template_project = ' + Pemberitahuan Penugasan Proyek
+
+ Tanggal: [tanggal_penugasan]
+
+ Detail Proyek:
+ ======================================
+ Nama Proyek: [nama_proyek]
+ Deskripsi: [deskripsi_proyek]
+ Batas Waktu: [batas_waktu]
+ Penanggung Jawab: [nama_superadmin]
+ ======================================
+
+ Harap segera mulai bekerja pada proyek ini dan laporkan perkembangan secara berkala.
+
+ Terima kasih.
+ [tim_manajemen] + '; + $template_followup = ' + Follow-Up Proyek
+
+ Tanggal: [tanggal_followup]
+
+ Detail Proyek:
+ ======================================
+ Nama Proyek: [nama_proyek]
+ Penanggung Jawab: [nama_karyawan]
+ Batas Waktu: [batas_waktu]
+ Status Terakhir: [status_terakhir]
+ ======================================
+
+ Harap berikan update mengenai perkembangan proyek ini dan jika ada kendala, silakan laporkan segera.
+
+ Terima kasih.
+ [tim_manajemen] + '; + Setting::create(['setting_key' => 'new_order', 'setting_value' => $template_order]); + Setting::create(['setting_key' => 'project_assignment', 'setting_value' => $template_project]); + Setting::create(['setting_key' => 'followup_project', 'setting_value' => $template_followup]); + Setting::create(['setting_key' => 'app_name', 'setting_value' => 'APP']); + Setting::create(['setting_key' => 'app_description', 'setting_value' => 'Asisten Notaris Online']); Setting::create(['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur']); Setting::create(['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf']); Setting::create(['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com']); From b34549bd0f6e713982bb5bf00c496fb72d74068a Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 17 Jan 2025 15:37:13 +0700 Subject: [PATCH 073/184] fix notif controller --- app/Http/Controllers/KaryawanController.php | 19 ------- .../Controllers/NotificationController.php | 36 +++++++++++++ app/Notifications/NewOrderNotification.php | 53 +++++++++++++++++++ routes/api.php | 3 +- 4 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 app/Http/Controllers/NotificationController.php create mode 100644 app/Notifications/NewOrderNotification.php diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 3afcb37..43561ee 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -133,25 +133,6 @@ public function store(Request $request) ], 200); } - public function sendJobdeskReminder(Request $request) - { - $request->validate([ - 'jobdesk_id' => 'required|integer|exists:jobdesks,id', - ]); - - $jobdesk = Jobdesk::find($request->jobdesk_id); - $user = User::find($jobdesk->user_id); - $data = [ - 'jobdesk_id' => $request->jobdesk_id, - 'user_id' => $user->id, - ]; - - // Kirim notifikasi - $user->notify(new PendingJobdesk($data)); - - return response()->json(['message' => 'Notifikasi jobdesk telah dikirim!']); - } - public function destroy($id) { $user = User::findOrFail($id); diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php new file mode 100644 index 0000000..d1f163b --- /dev/null +++ b/app/Http/Controllers/NotificationController.php @@ -0,0 +1,36 @@ +validate([ + 'jobdesk_id' => 'required|integer|exists:jobdesks,id', + 'message' => 'required|string|max:255', + ]); + + // Ambil jobdesk dan pengguna terkait + $jobdesk = Jobdesk::find($request->jobdesk_id); + $user = User::find($jobdesk->user_id); + + // Kirim notifikasi + Notification::send($user, new NewOrderNotification($request->message)); + + return response()->json(['message' => 'Notifikasi pengingat jobdesk berhasil dikirim!']); + } +} diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php new file mode 100644 index 0000000..5896739 --- /dev/null +++ b/app/Notifications/NewOrderNotification.php @@ -0,0 +1,53 @@ +message = Setting::where('setting_key', 'new_order')->value('setting_value') ?? 'Pesan default jika tidak ada setting'; + } + + /** + * Tentukan saluran mana yang akan digunakan untuk mengirim notifikasi. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; // Anda bisa menambahkan saluran lain seperti database, broadcast, dsb. + } + + /** + * Siapkan pesan email untuk notifikasi. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage) + ->subject('Notifikasi Pesanan Baru') + ->line($this->message) + ->action('Lihat Pesanan', url('/orders')) // Sesuaikan URL sesuai kebutuhan Anda + ->line('Terima kasih telah menggunakan aplikasi kami!'); + } +} diff --git a/routes/api.php b/routes/api.php index 1233f6a..0ea635e 100644 --- a/routes/api.php +++ b/routes/api.php @@ -12,13 +12,14 @@ use App\Http\Controllers\ProductController; use App\Http\Controllers\DataController; use App\Http\Controllers\Auth\ProfileController; +use Illuminate\Notifications\NotificationController; Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { return $request->user(); }); Route::get('user', [UserController::class, 'index']); - Route::post('jobdesk-reminder', [KaryawanController::class, 'sendJobdeskReminder']); + Route::post('jobdesk-reminder', [NotificationController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('home', [DashboardController::class, 'index']); Route::apiResources([ From 969acc3cc7c7dfaf1590701bf1e582eac81da169 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 17 Jan 2025 20:53:07 +0700 Subject: [PATCH 074/184] fix end poin notif --- app/Http/Controllers/NotificationController.php | 2 +- routes/api.php | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php index d1f163b..2f0c8ed 100644 --- a/app/Http/Controllers/NotificationController.php +++ b/app/Http/Controllers/NotificationController.php @@ -21,7 +21,7 @@ public function sendJobdeskReminder(Request $request) // Validasi input $request->validate([ 'jobdesk_id' => 'required|integer|exists:jobdesks,id', - 'message' => 'required|string|max:255', + 'message' => 'nullable|string', ]); // Ambil jobdesk dan pengguna terkait diff --git a/routes/api.php b/routes/api.php index 0ea635e..97f8ef4 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,8 +11,9 @@ use App\Http\Controllers\UserController; use App\Http\Controllers\ProductController; use App\Http\Controllers\DataController; +use App\Http\Controllers\NotificationController; use App\Http\Controllers\Auth\ProfileController; -use Illuminate\Notifications\NotificationController; + Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { From a7e5473add375784dc0b8a4a9fe5119a07261a66 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 18 Jan 2025 14:13:38 +0700 Subject: [PATCH 075/184] fix seeder product --- app/Http/Controllers/OrderController.php | 25 +- database/seeders/DatabaseSeeder.php | 398 ----------------------- database/seeders/ProductSeeder.php | 372 +++++++++++++++++++++ database/seeders/UserSeeder.php | 57 ++++ 4 files changed, 448 insertions(+), 404 deletions(-) create mode 100644 database/seeders/ProductSeeder.php create mode 100644 database/seeders/UserSeeder.php diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index e52b1fb..7e5e6c9 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -5,6 +5,7 @@ use App\Models\Order; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Validator; class OrderController extends Controller { @@ -15,7 +16,7 @@ class OrderController extends Controller 'price' => 'required', 'paid' => 'required', 'payment_method' => 'required', - 'data' => 'required', + 'data' => 'nullable', 'customer_id' => 'required|exists:customers,id', ]; public function index(Request $request) @@ -109,13 +110,25 @@ public function update(Request $request, Order $order) public function store(Request $request) { - // Validate the incoming request - $validatedData = $request->validate($this->validate); + $validator = Validator::make($request->all(), [ + 'order_date' => 'required', + 'product_id' => 'required', + 'price' => 'required', + 'paid' => 'required', + 'payment_method' => 'required', + 'data' => 'required', + 'customer_id' => 'required|exists:customers,id', + ]); + + if ($validator->fails()) { + return response()->json([ + 'message' => 'Validation errors', + 'errors' => $validator->errors(), + ], 422); + } - // Create the order with validated data - $order = Order::create($validatedData); + $order = Order::create($validator->validated()); - // Return the created order as a JSON response return response()->json($order); } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 8e5d76d..ea965d8 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -4,7 +4,6 @@ use App\Models\Customer; use App\Models\Jobdesk; -use App\Models\User; use App\Models\Order; use App\Models\Setting; use App\Models\Product; @@ -21,406 +20,9 @@ class DatabaseSeeder extends Seeder public function run(): void { - $products = [ - 'perjanjian_kredit' => [ - 'title' => 'Perjanjian Kredit', - 'data' => [1, 2, 3, 4, 5, 6], - 'category' => 'perorangan' - ], - 'skmht' => [ - 'title' => 'SKMHT', - 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14, 7], - 'category' => 'perorangan' - ], - 'apht' => [ - 'title' => 'APHT', - 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14], - 'category' => 'perorangan' - ], - 'fidusia' => [ - 'title' => 'Fidusia', - 'data' => [2, 3, 15, 16, 17, 18, 19, 20, 21, 7], - 'category' => 'perorangan' - ], - 'jual_beli' => [ - 'title' => 'Jual Beli', - 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], - 'category' => 'perorangan', - ], - 'hibah' => [ - 'title' => 'Hibah', - 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], - 'category' => 'perorangan', - ], - 'turun_waris' => [ - 'title' => 'Turun Waris', - 'data' => [22, 23, 24, 25, 26, 27, 28, 29, 30], - 'category' => 'perorangan', - ], - 'pecah' => [ - 'title' => 'Pecah', - 'data' => [1, 44], - 'category' => 'perorangan', - ], - 'pendirian_pt' => [ - 'title' => 'Pendirian PT', - 'data' => [1, 2, 3, 42, 43, 21, 21, 44, 45, 41, 52], - 'category' => 'perorangan', - ], - 'pendirian_cv' => [ - 'title' => 'Pendirian CV', - 'data' => [1, 2, 3, 46, 47, 21, 21, 45, 41, 52], - 'category' => 'perorangan', - ], - 'pendirian_yayasan' => [ - 'title' => 'Pendirian Yayasan', - 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], - 'category' => 'perorangan', - ], - 'pendirian_pt_perseorangan' => [ - 'title' => 'Pendirian PT Perseorangan', - 'data' => [1, 2, 3, 42, 21, 45, 41, 52], - 'category' => 'perorangan', - ], - 'perubahan_pt' => [ - 'title' => 'Perubahan PT', - 'data' => [1, 2, 3, 42, 43, 21, 21, 44, 45, 41, 52], - 'category' => 'perorangan', - ], - 'perubahan_cv' => [ - 'title' => 'Perubahan CV', - 'data' => [1, 2, 3, 46, 47, 21, 21, 45, 41, 52], - 'category' => 'perorangan', - ], - 'perubahan_yayasan' => [ - 'title' => 'Perubahan Yayasan', - 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], - 'category' => 'perorangan', - ], - 'perubahan_pt_perseorangan' => [ - 'title' => 'Perubahan PT Perseorangan', - 'data' => [1, 2, 3, 42, 21, 45, 41, 52], - 'category' => 'perorangan', - ], - // BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat' - 'bpr_bba' => [ - 'title' => 'BPR BBA', - 'data' => [], - 'category' => 'bank', - ], - 'bpr_pala_pusat' => [ - 'title' => 'BPR Pala Pusat', - 'data' => [], - 'category' => 'bank', - ], - 'bpr_pala_cabang' => [ - 'title' => 'BPR Pala Cabang', - 'data' => [], - 'category' => 'bank', - ], - 'bpr_danamas_prime' => [ - 'title' => 'BPR Danamas Prime', - 'data' => [], - 'category' => 'bank', - ], - 'bpr_arum_mandiri' => [ - 'title' => 'BPR Arum Mandiri', - 'data' => [], - 'category' => 'bank', - ], - 'bprs_madina_mandiri' => [ - 'title' => 'BPRS Madina Mandiri', - 'data' => [], - 'category' => 'bank', - ], - 'bmt_sejahtera_ummat' => [ - 'title' => 'BMT Sejahtera Ummat', - 'data' => [], - 'category' => 'bank', - ] - ]; - $datas = [ - 1 => [ - 'title' => 'Judul Akta', - 'type' => 'text' - ], - 2 => [ - 'title' => 'Nomor Akta', - 'type' => 'text' - ], - 3 => [ - 'title' => 'Tanggal Akta', - 'type' => 'date' - ], - 4 => [ - 'title' => 'Yang Mengerjakan', - 'type' => 'text' - ], - 5 => [ - 'title' => 'Jumlah Pinjaman', - 'type' => 'number' - ], - 6 => [ - 'title' => 'Lain-lain', - 'type' => 'text' - ], - 7 => [ - 'title' => 'Tanggal Habis SKMHT', - 'type' => 'date' - ], - 8 => [ - 'title' => 'Nomor Agunan', - 'type' => 'text' - ], - 9 => [ - 'title' => 'NIB', - 'type' => 'text' - ], - 10 => [ - 'title' => 'NOP', - 'type' => 'text' - ], - 11 => [ - 'title' => 'Nama Pemilik Agunan', - 'type' => 'text' - ], - 12 => [ - 'title' => 'Kode Sertifikat', - 'type' => 'text' - ], - 13 => [ - 'title' => 'Nomor Seri', - 'type' => 'text' - ], - 14 => [ - 'title' => 'Jumlah Pengikatan', - 'type' => 'number' - ], - 15 => [ - 'title' => 'Jenis Agunan', - 'type' => 'text' - ], - 16 => [ - 'title' => 'Keterangan Objek', - 'type' => 'text' - ], - 17 => [ - 'title' => 'Bukti Kepemilikan Objek', - 'type' => 'text' - ], - 18 => [ - 'title' => 'Nilai Objek', - 'type' => 'number' - ], - 19 => [ - 'title' => 'Pemilik Agunan', - 'type' => 'text' - ], - 20 => [ - 'title' => 'Nilai Penjaminan', - 'type' => 'number' - ], - 21 => [ - 'title' => 'NPWP', - 'type' => 'text' - ], - 22 => [ - 'title' => 'Berkas Masuk', - 'type' => 'text' - ], - 23 => [ - 'title' => 'Pewaris', - 'type' => 'text' - ], - 24 => [ - 'title' => 'Ahli Waris', - 'type' => 'text' - ], - 25 => [ - 'title' => 'Penerima Waris', - 'type' => 'text' - ], - 26 => [ - 'title' => 'Lokasi Tanah', - 'type' => 'text' - ], - 27 => [ - 'title' => 'Nilai Pajak', - 'type' => 'number' - ], - 28 => [ - 'title' => 'Berkas Kembali', - 'type' => 'text' - ], - 29 => [ - 'title' => 'Masuk BPN', - 'type' => 'text' - ], - 30 => [ - 'title' => 'Tanggal Akad', - 'type' => 'date' - ], - 31 => [ - 'title' => 'Nama Penjual', - 'type' => 'text' - ], - 32 => [ - 'title' => 'Nama Pembeli', - 'type' => 'text' - ], - 33 => [ - 'title' => 'Sertifikat', - 'type' => 'text' - ], - 34 => [ - 'title' => 'Nilai Jual Beli', - 'type' => 'number' - ], - 35 => [ - 'title' => 'Nilai SSB', - 'type' => 'number' - ], - 36 => [ - 'title' => 'Nilai SSP', - 'type' => 'number' - ], - 37 => [ - 'title' => 'Keterangan PPJB', - 'type' => 'text' - ], - 38 => [ - 'title' => 'Keterangan Kuasa Menjual', - 'type' => 'text' - ], - 39 => [ - 'title' => 'Harga Real', - 'type' => 'number' - ], - 40 => [ - 'title' => 'Harga Kesepakatan', - 'type' => 'number' - ], - 41 => [ - 'title' => 'Biaya', - 'type' => 'number' - ], - 42 => [ - 'title' => 'Nama Direktur', - 'type' => 'text' - ], - 43 => [ - 'title' => 'Nama Komisaris', - 'type' => 'text' - ], - 44 => [ - 'title' => 'Nama Pemilik Manfaat', - 'type' => 'text' - ], - 45 => [ - 'title' => 'Kedudukan PT', - 'type' => 'text' - ], - 46 => [ - 'title' => 'Nama Persero Aktif', - 'type' => 'text' - ], - 47 => [ - 'title' => 'Nama Persero Pasif', - 'type' => 'text' - ], - 48 => [ - 'title' => 'Nama Pembina', - 'type' => 'text' - ], - 49 => [ - 'title' => 'Nama Ketua', - 'type' => 'text' - ], - 50 => [ - 'title' => 'Nama Wakil', - 'type' => 'text' - ], - 51 => [ - 'title' => 'Nama Bendahara', - 'type' => 'text' - ], - 52 => [ - 'title' => 'Tanggal Upload', - 'type' => 'date' - ] - ]; - User::factory()->create([ - 'name' => 'Test Admin', - 'email' => 'test@larapi.test', - 'is_admin' => true, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Manager', - 'password' => Hash::make('password'), - ]); - User::factory()->create([ - 'name' => 'Test Manager', - 'email' => 'manager@larapi.test', - 'is_admin' => false, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Manager', - 'password' => Hash::make('password'), - ]); - User::factory()->create([ - 'name' => 'Test Keuangan', - 'email' => 'keuangan@larapi.test', - 'is_admin' => false, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Keuangan', - 'password' => Hash::make('password'), - ]); - User::factory()->create([ - 'name' => 'Test ', - 'email' => 'staff@larapi.test', - 'is_admin' => false, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Staff', - 'password' => Hash::make('password'), - ]); - - // Membuat 30 pengguna - User::factory(25)->create(); - - // Membuat 5 customer $customers = Customer::factory(35)->create(); - foreach ($datas as $id => $data) { - Data::factory()->create([ - 'id' => $id, - 'name' => $data['title'], - 'type' => $data['type'] - ]); - } - - // Insert data ke tabel 'products' dan 'data_product' - foreach ($products as $slug => $product) { - $productId = Product::factory()->create([ - 'name' => $product['title'], - 'description' => '-', - 'category' => $product['category'] - ]); - - foreach ($product['data'] as $dataId) { - DataProduct::factory()->create([ - 'data_id' => $dataId, - 'product_id' => $productId - ]); - } - } - foreach ($customers as $customer) { // Membuat antara 2 hingga 10 order untuk setiap customer $ordersCount = rand(2, 10); diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php new file mode 100644 index 0000000..5030366 --- /dev/null +++ b/database/seeders/ProductSeeder.php @@ -0,0 +1,372 @@ + [ + 'title' => 'Perjanjian Kredit', + 'data' => [1, 2, 3, 4, 5, 6], + 'category' => 'perorangan' + ], + 'skmht' => [ + 'title' => 'SKMHT', + 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14, 7], + 'category' => 'perorangan' + ], + 'apht' => [ + 'title' => 'APHT', + 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14], + 'category' => 'perorangan' + ], + 'fidusia' => [ + 'title' => 'Fidusia', + 'data' => [2, 3, 15, 16, 17, 18, 19, 20, 21, 7], + 'category' => 'perorangan' + ], + 'jual_beli' => [ + 'title' => 'Jual Beli', + 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'category' => 'perorangan', + ], + 'hibah' => [ + 'title' => 'Hibah', + 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'category' => 'perorangan', + ], + 'turun_waris' => [ + 'title' => 'Turun Waris', + 'data' => [22, 23, 24, 25, 26, 27, 28, 29, 30], + 'category' => 'perorangan', + ], + 'pecah' => [ + 'title' => 'Pecah', + 'data' => [1, 44], + 'category' => 'perorangan', + ], + 'pendirian_pt' => [ + 'title' => 'Pendirian PT', + 'data' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], + 'category' => 'perorangan', + ], + 'pendirian_cv' => [ + 'title' => 'Pendirian CV', + 'data' => [1, 2, 3, 46, 47, 21, 45, 41, 52], + 'category' => 'perorangan', + ], + 'pendirian_yayasan' => [ + 'title' => 'Pendirian Yayasan', + 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'category' => 'perorangan', + ], + 'pendirian_pt_perseorangan' => [ + 'title' => 'Pendirian PT Perseorangan', + 'data' => [1, 2, 3, 42, 21, 45, 41, 52], + 'category' => 'perorangan', + ], + 'perubahan_pt' => [ + 'title' => 'Perubahan PT', + 'data' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], + 'category' => 'perorangan', + ], + 'perubahan_cv' => [ + 'title' => 'Perubahan CV', + 'data' => [1, 2, 3, 46, 47, 21, 45, 41, 52], + 'category' => 'perorangan', + ], + 'perubahan_yayasan' => [ + 'title' => 'Perubahan Yayasan', + 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'category' => 'perorangan', + ], + 'perubahan_pt_perseorangan' => [ + 'title' => 'Perubahan PT Perseorangan', + 'data' => [1, 2, 3, 42, 21, 45, 41, 52], + 'category' => 'perorangan', + ], + // BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat' + 'bpr_bba' => [ + 'title' => 'BPR BBA', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_pala_pusat' => [ + 'title' => 'BPR Pala Pusat', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_pala_cabang' => [ + 'title' => 'BPR Pala Cabang', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_danamas_prime' => [ + 'title' => 'BPR Danamas Prime', + 'data' => [], + 'category' => 'bank', + ], + 'bpr_arum_mandiri' => [ + 'title' => 'BPR Arum Mandiri', + 'data' => [], + 'category' => 'bank', + ], + 'bprs_madina_mandiri' => [ + 'title' => 'BPRS Madina Mandiri', + 'data' => [], + 'category' => 'bank', + ], + 'bmt_sejahtera_ummat' => [ + 'title' => 'BMT Sejahtera Ummat', + 'data' => [], + 'category' => 'bank', + ] + ]; + $datas = [ + 1 => [ + 'title' => 'Judul Akta', + 'type' => 'text' + ], + 2 => [ + 'title' => 'Nomor Akta', + 'type' => 'text' + ], + 3 => [ + 'title' => 'Tanggal Akta', + 'type' => 'date' + ], + 4 => [ + 'title' => 'Yang Mengerjakan', + 'type' => 'text' + ], + 5 => [ + 'title' => 'Jumlah Pinjaman', + 'type' => 'number' + ], + 6 => [ + 'title' => 'Lain-lain', + 'type' => 'text' + ], + 7 => [ + 'title' => 'Tanggal Habis SKMHT', + 'type' => 'date' + ], + 8 => [ + 'title' => 'Nomor Agunan', + 'type' => 'text' + ], + 9 => [ + 'title' => 'NIB', + 'type' => 'text' + ], + 10 => [ + 'title' => 'NOP', + 'type' => 'text' + ], + 11 => [ + 'title' => 'Nama Pemilik Agunan', + 'type' => 'text' + ], + 12 => [ + 'title' => 'Kode Sertifikat', + 'type' => 'text' + ], + 13 => [ + 'title' => 'Nomor Seri', + 'type' => 'text' + ], + 14 => [ + 'title' => 'Jumlah Pengikatan', + 'type' => 'number' + ], + 15 => [ + 'title' => 'Jenis Agunan', + 'type' => 'text' + ], + 16 => [ + 'title' => 'Keterangan Objek', + 'type' => 'text' + ], + 17 => [ + 'title' => 'Bukti Kepemilikan Objek', + 'type' => 'text' + ], + 18 => [ + 'title' => 'Nilai Objek', + 'type' => 'number' + ], + 19 => [ + 'title' => 'Pemilik Agunan', + 'type' => 'text' + ], + 20 => [ + 'title' => 'Nilai Penjaminan', + 'type' => 'number' + ], + 21 => [ + 'title' => 'NPWP', + 'type' => 'text' + ], + 22 => [ + 'title' => 'Berkas Masuk', + 'type' => 'text' + ], + 23 => [ + 'title' => 'Pewaris', + 'type' => 'text' + ], + 24 => [ + 'title' => 'Ahli Waris', + 'type' => 'text' + ], + 25 => [ + 'title' => 'Penerima Waris', + 'type' => 'text' + ], + 26 => [ + 'title' => 'Lokasi Tanah', + 'type' => 'text' + ], + 27 => [ + 'title' => 'Nilai Pajak', + 'type' => 'number' + ], + 28 => [ + 'title' => 'Berkas Kembali', + 'type' => 'text' + ], + 29 => [ + 'title' => 'Masuk BPN', + 'type' => 'text' + ], + 30 => [ + 'title' => 'Tanggal Akad', + 'type' => 'date' + ], + 31 => [ + 'title' => 'Nama Penjual', + 'type' => 'text' + ], + 32 => [ + 'title' => 'Nama Pembeli', + 'type' => 'text' + ], + 33 => [ + 'title' => 'Sertifikat', + 'type' => 'text' + ], + 34 => [ + 'title' => 'Nilai Jual Beli', + 'type' => 'number' + ], + 35 => [ + 'title' => 'Nilai SSB', + 'type' => 'number' + ], + 36 => [ + 'title' => 'Nilai SSP', + 'type' => 'number' + ], + 37 => [ + 'title' => 'Keterangan PPJB', + 'type' => 'text' + ], + 38 => [ + 'title' => 'Keterangan Kuasa Menjual', + 'type' => 'text' + ], + 39 => [ + 'title' => 'Harga Real', + 'type' => 'number' + ], + 40 => [ + 'title' => 'Harga Kesepakatan', + 'type' => 'number' + ], + 41 => [ + 'title' => 'Biaya', + 'type' => 'number' + ], + 42 => [ + 'title' => 'Nama Direktur', + 'type' => 'text' + ], + 43 => [ + 'title' => 'Nama Komisaris', + 'type' => 'text' + ], + 44 => [ + 'title' => 'Nama Pemilik Manfaat', + 'type' => 'text' + ], + 45 => [ + 'title' => 'Kedudukan PT', + 'type' => 'text' + ], + 46 => [ + 'title' => 'Nama Persero Aktif', + 'type' => 'text' + ], + 47 => [ + 'title' => 'Nama Persero Pasif', + 'type' => 'text' + ], + 48 => [ + 'title' => 'Nama Pembina', + 'type' => 'text' + ], + 49 => [ + 'title' => 'Nama Ketua', + 'type' => 'text' + ], + 50 => [ + 'title' => 'Nama Wakil', + 'type' => 'text' + ], + 51 => [ + 'title' => 'Nama Bendahara', + 'type' => 'text' + ], + 52 => [ + 'title' => 'Tanggal Upload', + 'type' => 'date' + ] + ]; + + // Membuat 5 customer + + foreach ($datas as $id => $data) { + Data::factory()->create([ + 'id' => $id, + 'name' => $data['title'], + 'type' => $data['type'] + ]); + } + + // Insert data ke tabel 'products' dan 'data_product' + foreach ($products as $slug => $product) { + $productId = Product::factory()->create([ + 'name' => $product['title'], + 'description' => '-', + 'category' => $product['category'] + ]); + + foreach ($product['data'] as $dataId) { + DataProduct::factory()->create([ + 'data_id' => $dataId, + 'product_id' => $productId + ]); + } + } + } +} diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php new file mode 100644 index 0000000..020cc8b --- /dev/null +++ b/database/seeders/UserSeeder.php @@ -0,0 +1,57 @@ +create([ + 'name' => 'Test Admin', + 'email' => 'test@larapi.test', + 'is_admin' => true, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Manager', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test Manager', + 'email' => 'manager@larapi.test', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Manager', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test Keuangan', + 'email' => 'keuangan@larapi.test', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Keuangan', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test ', + 'email' => 'staff@larapi.test', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Staff', + 'password' => Hash::make('password'), + ]); + + // Membuat 30 pengguna + User::factory(25)->create(); + } +} From 3353f163b6aac51af8927f562bac466c32bd5e4b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 19 Jan 2025 20:54:46 +0700 Subject: [PATCH 076/184] remove jobdesk collumn --- app/Models/JobDesk.php | 1 - database/migrations/2024_11_23_124844_create_jobdesks_table.php | 1 - 2 files changed, 2 deletions(-) diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php index 73eb8e3..fbe770a 100644 --- a/app/Models/JobDesk.php +++ b/app/Models/JobDesk.php @@ -13,7 +13,6 @@ class Jobdesk extends Model 'customer_id', 'order_id', 'user_id', - 'jobdesk', 'tanggal_pengerjaan', 'tanggal_selesai', 'status', diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php index a211eb4..58c0ce9 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -16,7 +16,6 @@ public function up(): void $table->string('customer_id'); $table->string('order_id'); $table->string('user_id')->nullable(); - $table->string('jobdesk'); $table->date('tanggal_pengerjaan')->nullable(); $table->date('tanggal_selesai')->nullable(); $table->string('status')->nullable(); From a09f32ab64b942a874622e3b638134e7214f871f Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 20 Jan 2025 08:58:57 +0700 Subject: [PATCH 077/184] fix jobdesk controller --- app/Http/Controllers/JobdeskController.php | 2 +- database/factories/JobDeskFactory.php | 2 -- .../migrations/2024_11_23_124844_create_jobdesks_table.php | 1 - database/seeders/DatabaseSeeder.php | 4 ---- 4 files changed, 1 insertion(+), 8 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index e8eef40..1134b90 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -15,7 +15,7 @@ public function index(Request $request) $user_id = $request->query('user_id'); // Initialize the query - $query = Jobdesk::with('customer', 'order', 'user', 'order.product'); + $query = Jobdesk::with('order', 'order.customer', 'user', 'order.product'); // Filter by order_id if provided if ($orderId) { diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 21ee5be..fa5bcab 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -23,8 +23,6 @@ public function definition(): array return [ 'order_id' => fake()->numberBetween(1, 10), 'user_id' => $status !== 'Masuk' ? fake()->numberBetween(1, 10) : null, - 'customer_id' => fake()->numberBetween(1, 10), - 'jobdesk' => fake()->randomElement(['Pengumpulan berkas', 'Pengerjaan tahap 1', 'Pengerjaan tahap 2', 'Pengerjaan tahap 3']), 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, 'tanggal_selesai' => $status === 'Selesai' ? now() : null, 'status' => $status diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php index 58c0ce9..51aa8c6 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -13,7 +13,6 @@ public function up(): void { Schema::create('jobdesks', function (Blueprint $table) { $table->id(); - $table->string('customer_id'); $table->string('order_id'); $table->string('user_id')->nullable(); $table->date('tanggal_pengerjaan')->nullable(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index ea965d8..81b8009 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -6,9 +6,6 @@ use App\Models\Jobdesk; use App\Models\Order; use App\Models\Setting; -use App\Models\Product; -use App\Models\Data; -use App\Models\DataProduct; use Illuminate\Database\Seeder; use Illuminate\Support\Facades\Hash; @@ -33,7 +30,6 @@ public function run(): void $jobdesksCount = rand(2, 10); Jobdesk::factory($jobdesksCount)->create([ 'order_id' => $order->id, - 'customer_id' => $customer->id ]); } } From 04cb90c797eddb5bd8e4079c7c06ef8c2371495a Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 20 Jan 2025 14:20:31 +0700 Subject: [PATCH 078/184] fix notification table --- app/Http/Controllers/OrderController.php | 8 ++- app/Notifications/NewOrderNotification.php | 58 +++++++++++++++++-- ...2_17_145546_create_notifications_table.php | 2 +- database/seeders/DatabaseSeeder.php | 3 +- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 7e5e6c9..5f87aea 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -3,9 +3,12 @@ namespace App\Http\Controllers; use App\Models\Order; +use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Validator; +use App\Notifications\NewOrderNotification; +use Illuminate\Support\Facades\Notification; class OrderController extends Controller { @@ -116,7 +119,7 @@ public function store(Request $request) 'price' => 'required', 'paid' => 'required', 'payment_method' => 'required', - 'data' => 'required', + 'data' => 'nullable', 'customer_id' => 'required|exists:customers,id', ]); @@ -128,7 +131,8 @@ public function store(Request $request) } $order = Order::create($validator->validated()); - + $users = User::where('is_admin', 1)->orWhere('position', 'owner')->get(); + Notification::send($users, new NewOrderNotification($order)); return response()->json($order); } diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index 5896739..b28d509 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -6,23 +6,52 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; -use App\Models\Setting; // Import model Setting +use App\Models\Setting; + +use Illuminate\Support\Facades\Log; class NewOrderNotification extends Notification implements ShouldQueue { use Queueable; protected $message; + protected $order; /** * Buat instance notifikasi baru. * * Ambil pesan dari pengaturan. */ - public function __construct() + public function __construct($order) { // Ambil pesan dari pengaturan $this->message = Setting::where('setting_key', 'new_order')->value('setting_value') ?? 'Pesan default jika tidak ada setting'; + + // Simpan informasi order + $this->order = $order; + + // replace [xxxx] with actual values + $this->message = str_replace( + [ + '[nama_klien]', + '[tanggal_order]', + '[no_telp]', + '[alamat]', + '[order_number]', + '[product]', + '[tim_manajemen]', + ], + [ + $order->customer->name . ' ' . $order, + $order->order_date, + $order->customer->phone, + $order->customer->alamat, + $order->order_number, + $order->product->name . ' (' . $order->product->category . ')', + 'Tim Manajemen' . Setting::where('setting_key', 'app_name')->value('setting_value'), + ], + $this->message + ); } /** @@ -33,7 +62,7 @@ public function __construct() */ public function via($notifiable) { - return ['mail']; // Anda bisa menambahkan saluran lain seperti database, broadcast, dsb. + return ['mail', 'database']; // Anda bisa menambahkan saluran lain seperti database, broadcast, dsb. } /** @@ -47,7 +76,28 @@ public function toMail($notifiable) return (new MailMessage) ->subject('Notifikasi Pesanan Baru') ->line($this->message) - ->action('Lihat Pesanan', url('/orders')) // Sesuaikan URL sesuai kebutuhan Anda + ->line('Tanggal Pesanan: ' . $this->order->order_date) + ->action('Lihat Pesanan', url('/orders')) ->line('Terima kasih telah menggunakan aplikasi kami!'); } + + /** + * Siapkan pesan database untuk notifikasi. + * + * @param mixed $notifiable + * @return array + */ + public function toDatabase($notifiable) + { + $data = [ + 'message' => $this->message, + 'user_id' => $notifiable->id, + 'order_id' => $this->order->id, + 'jobdesk_id' => $this->order->jobdesk_id + ]; + + Log::info('Sending notification data to database:', $data); + + return $data; + } } diff --git a/database/migrations/2024_12_17_145546_create_notifications_table.php b/database/migrations/2024_12_17_145546_create_notifications_table.php index e76414c..d738032 100644 --- a/database/migrations/2024_12_17_145546_create_notifications_table.php +++ b/database/migrations/2024_12_17_145546_create_notifications_table.php @@ -14,7 +14,7 @@ public function up(): void Schema::create('notifications', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('type'); - $table->string('notifiable_type', 191); + $table->morphs('notifiable'); $table->text('data'); $table->timestamp('read_at')->nullable(); $table->timestamps(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 81b8009..5dada8b 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -41,9 +41,8 @@ public function run(): void
Detail Order:
======================================
- Nama Klien: [Nama Klien]
+ Nama Klien: [nama_klien]
Nomor Telepon: [no_telp]
- Email: [email]
Jenis Layanan Notaris: [product]
======================================

From 22fac3620457365710b0f88c2f8aaa6d1005512c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 20 Jan 2025 15:16:16 +0700 Subject: [PATCH 079/184] change toDatabase data --- ...mailVerificationNotificationController.php | 2 +- .../Controllers/NotificationController.php | 34 ++++-------------- .../SendNotificationController.php | 36 +++++++++++++++++++ app/Notifications/NewOrderNotification.php | 17 +++------ routes/api.php | 6 ++-- routes/auth.php | 4 +-- 6 files changed, 54 insertions(+), 45 deletions(-) create mode 100644 app/Http/Controllers/SendNotificationController.php diff --git a/app/Http/Controllers/Auth/EmailVerificationNotificationController.php b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php index 0550fbd..3f42fcd 100644 --- a/app/Http/Controllers/Auth/EmailVerificationNotificationController.php +++ b/app/Http/Controllers/Auth/EmailVerificationNotificationController.php @@ -7,7 +7,7 @@ use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; -class EmailVerificationNotificationController extends Controller +class EmailVerificationSendNotificationController extends Controller { /** * Send a new email verification notification. diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php index 2f0c8ed..46425d9 100644 --- a/app/Http/Controllers/NotificationController.php +++ b/app/Http/Controllers/NotificationController.php @@ -2,35 +2,13 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; -use App\Notifications\NewOrderNotification; -use App\Models\User; -use App\Models\Jobdesk; // Pastikan Anda mengimpor model Jobdesk -use Illuminate\Support\Facades\Notification; +use Illuminate\Support\Facades\Auth; class NotificationController extends Controller { - /** - * Mengirim pengingat jobdesk ke pengguna. - * - * @param \Illuminate\Http\Request $request - * @return \Illuminate\Http\Response - */ - public function sendJobdeskReminder(Request $request) - { - // Validasi input - $request->validate([ - 'jobdesk_id' => 'required|integer|exists:jobdesks,id', - 'message' => 'nullable|string', - ]); - - // Ambil jobdesk dan pengguna terkait - $jobdesk = Jobdesk::find($request->jobdesk_id); - $user = User::find($jobdesk->user_id); - - // Kirim notifikasi - Notification::send($user, new NewOrderNotification($request->message)); - - return response()->json(['message' => 'Notifikasi pengingat jobdesk berhasil dikirim!']); - } + public function index() + { + $notifications = Auth::user()->notifications; + return response()->json($notifications); + } } diff --git a/app/Http/Controllers/SendNotificationController.php b/app/Http/Controllers/SendNotificationController.php new file mode 100644 index 0000000..5ff708c --- /dev/null +++ b/app/Http/Controllers/SendNotificationController.php @@ -0,0 +1,36 @@ +validate([ + 'jobdesk_id' => 'required|integer|exists:jobdesks,id', + 'message' => 'nullable|string', + ]); + + // Ambil jobdesk dan pengguna terkait + $jobdesk = Jobdesk::find($request->jobdesk_id); + $user = User::find($jobdesk->user_id); + + // Kirim notifikasi + Notification::send($user, new NewOrderNotification($request->message)); + + return response()->json(['message' => 'Notifikasi pengingat jobdesk berhasil dikirim!']); + } +} diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index b28d509..849eaab 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -30,7 +30,6 @@ public function __construct($order) // Simpan informasi order $this->order = $order; - // replace [xxxx] with actual values $this->message = str_replace( [ '[nama_klien]', @@ -42,13 +41,13 @@ public function __construct($order) '[tim_manajemen]', ], [ - $order->customer->name . ' ' . $order, + $order->customer->name, $order->order_date, $order->customer->phone, $order->customer->alamat, $order->order_number, $order->product->name . ' (' . $order->product->category . ')', - 'Tim Manajemen' . Setting::where('setting_key', 'app_name')->value('setting_value'), + 'Tim Manajemen ' . Setting::where('setting_key', 'app_name')->value('setting_value'), ], $this->message ); @@ -89,15 +88,9 @@ public function toMail($notifiable) */ public function toDatabase($notifiable) { - $data = [ - 'message' => $this->message, - 'user_id' => $notifiable->id, - 'order_id' => $this->order->id, - 'jobdesk_id' => $this->order->jobdesk_id + return [ + 'message' => 'Pemberitahuan: Pesanan Baru', + 'notifiable' => $notifiable ]; - - Log::info('Sending notification data to database:', $data); - - return $data; } } diff --git a/routes/api.php b/routes/api.php index 97f8ef4..65482b2 100644 --- a/routes/api.php +++ b/routes/api.php @@ -11,8 +11,9 @@ use App\Http\Controllers\UserController; use App\Http\Controllers\ProductController; use App\Http\Controllers\DataController; -use App\Http\Controllers\NotificationController; +use App\Http\Controllers\SendNotificationController; use App\Http\Controllers\Auth\ProfileController; +use App\Http\Controllers\NotificationController; Route::middleware(['auth:sanctum'])->group(function () { @@ -20,9 +21,10 @@ return $request->user(); }); Route::get('user', [UserController::class, 'index']); - Route::post('jobdesk-reminder', [NotificationController::class, 'sendJobdeskReminder']); + Route::post('jobdesk-reminder', [SendNotificationController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('home', [DashboardController::class, 'index']); + Route::get('notifications', [NotificationController::class, 'index']); Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, diff --git a/routes/auth.php b/routes/auth.php index 9cf5ffd..4170a7e 100644 --- a/routes/auth.php +++ b/routes/auth.php @@ -1,7 +1,7 @@ middleware(['auth', 'signed', 'throttle:6,1']) ->name('verification.verify'); -Route::post('/email/verification-notification', [EmailVerificationNotificationController::class, 'store']) +Route::post('/email/verification-notification', [EmailVerificationSendNotificationController::class, 'store']) ->middleware(['auth', 'throttle:6,1']) ->name('verification.send'); From 0271ef3597eacf567c6dc616ade776e123ea7ea6 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 20 Jan 2025 15:30:10 +0700 Subject: [PATCH 080/184] change data notification format --- app/Notifications/NewOrderNotification.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index 849eaab..6e3049d 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -89,8 +89,8 @@ public function toMail($notifiable) public function toDatabase($notifiable) { return [ - 'message' => 'Pemberitahuan: Pesanan Baru', - 'notifiable' => $notifiable + 'message' => 'Pesanan baru telah diterima dari ' . $this->order->customer->name, + 'order_id' => $this->order->id, ]; } } From 96285f31eb1ea8816e6f8b9ac5e0cca0f49b801c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 20 Jan 2025 22:19:21 +0700 Subject: [PATCH 081/184] fix order controller --- app/Http/Controllers/NotificationController.php | 9 +++++++++ app/Http/Controllers/OrderController.php | 7 +++++++ app/Notifications/NewOrderNotification.php | 2 +- routes/api.php | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php index 46425d9..a4699c8 100644 --- a/app/Http/Controllers/NotificationController.php +++ b/app/Http/Controllers/NotificationController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use Illuminate\Support\Facades\Auth; +use Illuminate\Http\Request; class NotificationController extends Controller { @@ -11,4 +12,12 @@ public function index() $notifications = Auth::user()->notifications; return response()->json($notifications); } + + public function update($id) + { + $notification = Auth::user()->notifications()->find($id); + $notification->markAsRead(); + + return response()->json($notification); + } } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 5f87aea..a1612ca 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -27,6 +27,7 @@ public function index(Request $request) $customerId = $request->query('customer_id'); $paginanate = $request->query('paginanate'); $name = $request->query('name'); + $product = $request->query('product'); $status = $request->query('status'); $status = isset($status) ? $status : null; @@ -42,6 +43,12 @@ public function index(Request $request) }); } + if ($product && strlen($product) > 2) { + $query->whereHas('product', function ($query) use ($product) { + $query->where('name', 'like', '%' . $product . '%'); + }); + } + if ($status) { $query->whereDoesntHave('jobdesks', function ($query) use ($status) { $query->where('status', '!=', 'Selesai'); diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index 6e3049d..c5fd511 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -90,7 +90,7 @@ public function toDatabase($notifiable) { return [ 'message' => 'Pesanan baru telah diterima dari ' . $this->order->customer->name, - 'order_id' => $this->order->id, + 'notifiable' => $notifiable, ]; } } diff --git a/routes/api.php b/routes/api.php index 65482b2..5f267c4 100644 --- a/routes/api.php +++ b/routes/api.php @@ -25,6 +25,7 @@ Route::put('profile', [ProfileController::class, 'update']); Route::get('home', [DashboardController::class, 'index']); Route::get('notifications', [NotificationController::class, 'index']); + Route::put('notifications/{id}', [NotificationController::class, 'update']); Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From f1cd4926716a4bc2372e8233466d185d87998faf Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 21 Jan 2025 13:05:28 +0700 Subject: [PATCH 082/184] fix unique phone --- app/Http/Controllers/CustomerController.php | 30 ++++++++++++++++--- ...24_11_01_021016_create_customers_table.php | 2 +- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 0b7ebb1..8765cee 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -19,7 +19,7 @@ class CustomerController extends Controller public function index(Request $request) { - + $paginate = $request->query('paginate'); $validated = $request->validate([ 'name' => 'nullable|string|min:3', 'phone' => 'nullable|string|min:4', @@ -37,7 +37,11 @@ public function index(Request $request) $query->orderBy('created_at', 'desc'); - $customers = $query->paginate(25); + if ($paginate === 'false') { + $customers = $query->get(); + } else { + $customers = $query->paginate(25); + } return response()->json($customers); } @@ -47,7 +51,19 @@ public function index(Request $request) */ public function store(Request $request) { - $validatedData = $request->validate($this->validate); + $validatedData = $request->validate( + [ + 'name' => 'required|string|max:255', + 'phone' => 'required|string|max:20|unique:customers,phone', + 'alamat' => 'required|string', + ], + [ + 'name.required' => 'Nama harus diisi.', + 'phone.required' => 'Nomor telepon harus diisi.', + 'phone.unique' => 'Nomor telepon sudah ada.', + 'alamat.required' => 'Alamat harus diisi.', + ] + ); $customer = Customer::create($validatedData); return response()->json($customer); @@ -68,7 +84,13 @@ public function show(Customer $customer) public function update(Request $request, Customer $customer) { $customer = Customer::find($customer->id); - $validatedData = $request->validate($this->validate); + $validatedData = $request->validate( + [ + 'name' => 'required|string|max:255', + 'phone' => 'required|string|max:20|unique:customers,phone,' . $customer->id, + 'alamat' => 'required|string', + ] + ); $customer->update($validatedData); return response()->json($customer); } diff --git a/database/migrations/2024_11_01_021016_create_customers_table.php b/database/migrations/2024_11_01_021016_create_customers_table.php index f2ab32f..b68196b 100644 --- a/database/migrations/2024_11_01_021016_create_customers_table.php +++ b/database/migrations/2024_11_01_021016_create_customers_table.php @@ -14,7 +14,7 @@ public function up(): void Schema::create('customers', function (Blueprint $table) { $table->id(); $table->string('name', 100); - $table->string('phone', 20); + $table->string('phone', 20)->unique(); $table->string('alamat', 255)->nullable(); $table->timestamps(); }); From 3c721194d707fa0a19a22a8c7aa81a3b2c1d6c19 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 21 Jan 2025 15:25:15 +0700 Subject: [PATCH 083/184] add description in jobdesk --- app/Http/Controllers/DataController.php | 8 +++++++- app/Http/Controllers/JobdeskController.php | 2 +- app/Models/Customer.php | 5 ----- app/Models/JobDesk.php | 8 +------- database/factories/JobDeskFactory.php | 1 + .../2024_11_23_124844_create_jobdesks_table.php | 1 + 6 files changed, 11 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/DataController.php b/app/Http/Controllers/DataController.php index 19113b5..2347c36 100644 --- a/app/Http/Controllers/DataController.php +++ b/app/Http/Controllers/DataController.php @@ -12,7 +12,13 @@ class DataController extends Controller */ public function index(Request $request) { - $data = Data::all(); + $paginanate = $request->query('paginanate'); + + if ($paginanate === 'false') { + $data = Data::all(); + } else { + $data = Data::paginate(25); + } return response()->json($data); } diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 1134b90..d06646b 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -33,7 +33,7 @@ public function index(Request $request) } if ($name && strlen($name) > 2) { - $query->whereHas('customer', function ($query) use ($name) { + $query->whereHas('order.customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); }); } diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 1d0cf82..d84a0cf 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -19,9 +19,4 @@ public function orders() { return $this->hasMany(Order::class); } - - public function jobDesks() - { - return $this->hasMany(Jobdesk::class); - } } diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php index fbe770a..f6fad9f 100644 --- a/app/Models/JobDesk.php +++ b/app/Models/JobDesk.php @@ -10,19 +10,13 @@ class Jobdesk extends Model use HasFactory; protected $fillable = [ - 'customer_id', 'order_id', + 'deskripsi', 'user_id', 'tanggal_pengerjaan', 'tanggal_selesai', 'status', ]; - - public function customer() - { - return $this->belongsTo(Customer::class); - } - public function order() { return $this->belongsTo(Order::class); diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index fa5bcab..fd41341 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -22,6 +22,7 @@ public function definition(): array return [ 'order_id' => fake()->numberBetween(1, 10), + 'deskripsi' => fake()->sentence(), 'user_id' => $status !== 'Masuk' ? fake()->numberBetween(1, 10) : null, 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, 'tanggal_selesai' => $status === 'Selesai' ? now() : null, diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php index 51aa8c6..f700e81 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -14,6 +14,7 @@ public function up(): void Schema::create('jobdesks', function (Blueprint $table) { $table->id(); $table->string('order_id'); + $table->text('deskripsi'); $table->string('user_id')->nullable(); $table->date('tanggal_pengerjaan')->nullable(); $table->date('tanggal_selesai')->nullable(); From 13f30cbd25ff6fe88fdc4651595184dde2bef1e2 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 22 Jan 2025 15:32:48 +0700 Subject: [PATCH 084/184] change variable user id --- app/Http/Controllers/JobdeskController.php | 28 ++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index d06646b..3a25a6c 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -12,7 +12,7 @@ public function index(Request $request) $orderId = $request->query('order_id'); $status = $request->query('status'); $name = $request->query('name'); - $user_id = $request->query('user_id'); + $userId = $request->query('user_id'); // Initialize the query $query = Jobdesk::with('order', 'order.customer', 'user', 'order.product'); @@ -28,8 +28,8 @@ public function index(Request $request) } // Filter by user_id if provided - if ($user_id) { - $query->where('user_id', $user_id); + if ($userId) { + $query->where('user_id', $userId); } if ($name && strlen($name) > 2) { @@ -66,13 +66,21 @@ public function store(Request $request) public function update(Request $request, Jobdesk $jobdesk) { $jobdesk = Jobdesk::find($jobdesk->id); - $validatedData = $request->validate([ - 'order_id' => 'required|exists:orders,id', - 'user_id' => 'required|exists:users,id', - 'tanggal_pengerjaan' => 'nullable', - 'tanggal_selesai' => 'nullable', - 'status' => 'required', - ]); + $validatedData = $request->validate( + [ + 'order_id' => 'required|exists:orders,id', + 'user_id' => 'required|exists:users,id', + 'deskripsi' => 'nullable', + 'tanggal_pengerjaan' => 'nullable', + 'tanggal_selesai' => 'nullable', + 'status' => 'required', + ], + [ + 'order_id.required' => 'Pilih order yang akan dikerjakan.', + 'user_id.required' => 'Pilih karyawan yang akan mengerjakan jobdesk.', + 'status.required' => 'Status harus diisi.', + ] + ); if (isset($validatedData['tanggal_pengerjaan'])) { $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); } From b8e5b1f606dc1207fc3ae4861106ee4c8436fd06 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 23 Jan 2025 08:36:14 +0700 Subject: [PATCH 085/184] fix paginate typo --- app/Http/Controllers/DataController.php | 4 ++-- app/Http/Controllers/KaryawanController.php | 4 ++-- app/Http/Controllers/OrderController.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/DataController.php b/app/Http/Controllers/DataController.php index 2347c36..0fc60f7 100644 --- a/app/Http/Controllers/DataController.php +++ b/app/Http/Controllers/DataController.php @@ -12,9 +12,9 @@ class DataController extends Controller */ public function index(Request $request) { - $paginanate = $request->query('paginanate'); + $paginate = $request->query('paginate'); - if ($paginanate === 'false') { + if ($paginate === 'false') { $data = Data::all(); } else { $data = Data::paginate(25); diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 43561ee..3293bc8 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -16,7 +16,7 @@ class KaryawanController extends Controller public function index(Request $request) { - $paginanate = $request->query('paginanate'); + $paginate = $request->query('paginate'); $name = $request->query('name'); // Query dasar semua user @@ -30,7 +30,7 @@ public function index(Request $request) $query->orderBy('created_at', 'desc'); // Check if pagination should be disabled - if ($paginanate === 'false') { + if ($paginate === 'false') { // Get all records without pagination $users = $query->get(); } else { diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index a1612ca..65a027a 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -25,7 +25,7 @@ class OrderController extends Controller public function index(Request $request) { $customerId = $request->query('customer_id'); - $paginanate = $request->query('paginanate'); + $paginate = $request->query('paginate'); $name = $request->query('name'); $product = $request->query('product'); $status = $request->query('status'); @@ -69,7 +69,7 @@ public function index(Request $request) $query->orderBy('created_at', 'desc'); // Check if pagination should be disabled - if ($paginanate === 'false') { + if ($paginate === 'false') { // Get all records without pagination $orders = $query->get(); } else { From 260874be0387e2bd757e4f15d046119bd3a48216 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 23 Jan 2025 14:22:49 +0700 Subject: [PATCH 086/184] add nomer order --- app/Http/Controllers/OrderController.php | 29 +++++++------- app/Models/Order.php | 31 +++++++++++++++ database/factories/OrderFactory.php | 6 +-- .../2024_11_06_033508_create_orders_table.php | 1 + database/seeders/DatabaseSeeder.php | 39 +++++++++++-------- 5 files changed, 71 insertions(+), 35 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 65a027a..d81987c 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -37,7 +37,7 @@ public function index(Request $request) $query->where('customer_id', $customerId); } - if ($name && strlen($name) > 2) { + if ($name && strlen($name) > 2 && !$customerId) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); }); @@ -50,20 +50,21 @@ public function index(Request $request) } if ($status) { - $query->whereDoesntHave('jobdesks', function ($query) use ($status) { - $query->where('status', '!=', 'Selesai'); + // Filter berdasarkan status + $query->whereHas('jobdesks', function ($query) use ($status) { + // Jika status adalah 'Selesai', hanya ambil yang memiliki lampiran + if ($status === 'Selesai') { + $query->where('status', 'Selesai')->whereNotNull('lampiran'); + } + // Jika status adalah 'Arsip', hanya ambil yang tidak memiliki lampiran + elseif ($status === 'Arsip') { + $query->where('status', 'Arsip')->whereNull('lampiran'); + } + // Jika status bukan 'Selesai' atau 'Arsip', ambil yang tidak 'Selesai' + else { + $query->where('status', '!=', 'Selesai'); + } }); - if ($status === 'Selesai') { - $query->whereNotNull('lampiran'); - } - if ($status === 'Arsip') { - $query->whereNull('lampiran'); - } - $query->whereHas('jobdesks'); - } else { - $query->whereHas('jobdesks', function ($query) { - $query->where('status', '!=', 'Selesai'); - })->orWhereDoesntHave('jobdesks'); } $query->orderBy('created_at', 'desc'); diff --git a/app/Models/Order.php b/app/Models/Order.php index 0c53099..85600f9 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -4,12 +4,43 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use App\Models\Setting; class Order extends Model { use HasFactory; + protected $primaryKey = 'id'; + + protected static $appCode; + + protected static function boot() + { + parent::boot(); + + self::$appCode = Setting::where('setting_key', 'app_code')->value('setting_value') ?? 'AN'; + + static::creating(function ($model) { + $lastOrder = self::where('no_order', 'like', self::$appCode . '%') + ->orderBy('no_order', 'desc') + ->first(); + + // Mengambil angka dari no_order terakhir + $newIdNumber = 1; // Default jika tidak ada order sebelumnya + + if ($lastOrder) { + // Ambil angka dari no_order terakhir + $lastId = substr($lastOrder->no_order, strlen(self::$appCode)); + $newIdNumber = intval($lastId) + 1; // Tambahkan 1 + } + + // Buat no_order baru + $model->no_order = self::$appCode . str_pad($newIdNumber, 5, '0', STR_PAD_LEFT); + }); + } + protected $fillable = [ + 'no_order', 'customer_id', 'order_date', 'product_id', diff --git a/database/factories/OrderFactory.php b/database/factories/OrderFactory.php index fc28ade..06314f1 100644 --- a/database/factories/OrderFactory.php +++ b/database/factories/OrderFactory.php @@ -26,11 +26,7 @@ public function definition(): array 'price' => $price, 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), 'paid' => $paid, - 'data' => [ - 'ktp' => fake()->numberBetween(1, 10), - 'kk' => fake()->numberBetween(1, 10), - 'npwp' => fake()->numberBetween(1, 10), - ] + 'data' => null, ]; } } diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php index cf27a87..91dd3e2 100644 --- a/database/migrations/2024_11_06_033508_create_orders_table.php +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -13,6 +13,7 @@ public function up(): void { Schema::create('orders', function (Blueprint $table) { $table->id(); + $table->string('no_order')->unique(); $table->string('customer_id'); $table->date('order_date'); $table->string('product_id'); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 5dada8b..d9cac5a 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -7,7 +7,6 @@ use App\Models\Order; use App\Models\Setting; use Illuminate\Database\Seeder; -use Illuminate\Support\Facades\Hash; class DatabaseSeeder extends Seeder { @@ -16,24 +15,27 @@ class DatabaseSeeder extends Seeder */ public function run(): void { + // Seed settings first + $this->seedSettings(); - - $customers = Customer::factory(35)->create(); + // Seed customers and orders + $customers = Customer::factory(28)->create(); foreach ($customers as $customer) { - // Membuat antara 2 hingga 10 order untuk setiap customer - $ordersCount = rand(2, 10); + $ordersCount = rand(2, 4); $orders = Order::factory($ordersCount)->create(['customer_id' => $customer->id]); foreach ($orders as $order) { - // Membuat antara 2 hingga 10 jobdesk untuk setiap order - $jobdesksCount = rand(2, 10); + $jobdesksCount = rand(2, 5); Jobdesk::factory($jobdesksCount)->create([ 'order_id' => $order->id, ]); } } + } + protected function seedSettings() + { $template_order = ' Pemberitahuan Order Layanan Notaris Baru

@@ -87,14 +89,19 @@ public function run(): void Terima kasih.
[tim_manajemen] '; - Setting::create(['setting_key' => 'new_order', 'setting_value' => $template_order]); - Setting::create(['setting_key' => 'project_assignment', 'setting_value' => $template_project]); - Setting::create(['setting_key' => 'followup_project', 'setting_value' => $template_followup]); - Setting::create(['setting_key' => 'app_name', 'setting_value' => 'APP']); - Setting::create(['setting_key' => 'app_description', 'setting_value' => 'Asisten Notaris Online']); - Setting::create(['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur']); - Setting::create(['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf']); - Setting::create(['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com']); - Setting::create(['setting_key' => 'banks', 'setting_value' => 'BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat']); + $templates = [ + ['setting_key' => 'new_order', 'setting_value' => $template_order], + ['setting_key' => 'project_assignment', 'setting_value' => $template_project], + ['setting_key' => 'followup_project', 'setting_value' => $template_followup], + + ['setting_key' => 'app_name', 'setting_value' => 'APP'], + ['setting_key' => 'app_code', 'setting_value' => 'AN'], + ['setting_key' => 'app_description', 'setting_value' => 'Asisten Notaris Online'], + ['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], + ['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf'], + ['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com'], + ]; + + Setting::insert($templates); // Batch insert } } From 1cd4aebcec88b9f8e6b15075f9ebf602b9d7bf01 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 23 Jan 2025 15:50:16 +0700 Subject: [PATCH 087/184] fix filter order --- app/Http/Controllers/OrderController.php | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index d81987c..af9fcbf 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -50,21 +50,20 @@ public function index(Request $request) } if ($status) { - // Filter berdasarkan status - $query->whereHas('jobdesks', function ($query) use ($status) { - // Jika status adalah 'Selesai', hanya ambil yang memiliki lampiran - if ($status === 'Selesai') { - $query->where('status', 'Selesai')->whereNotNull('lampiran'); - } - // Jika status adalah 'Arsip', hanya ambil yang tidak memiliki lampiran - elseif ($status === 'Arsip') { - $query->where('status', 'Arsip')->whereNull('lampiran'); - } - // Jika status bukan 'Selesai' atau 'Arsip', ambil yang tidak 'Selesai' - else { - $query->where('status', '!=', 'Selesai'); - } + $query->whereDoesntHave('jobdesks', function ($query) use ($status) { + $query->where('status', '!=', 'Selesai'); }); + if ($status === 'Selesai') { + $query->whereNotNull('lampiran'); + } + if ($status === 'Arsip') { + $query->whereNull('lampiran'); + } + $query->whereHas('jobdesks'); + } else if (!($customerId || $name)) { + $query->whereHas('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->orWhereDoesntHave('jobdesks'); } $query->orderBy('created_at', 'desc'); From d3db13a4b6b5ce4256b7d5c458fee8c73e8cf600 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 24 Jan 2025 15:30:45 +0700 Subject: [PATCH 088/184] fix table structure --- app/Http/Controllers/CustomerController.php | 6 - app/Http/Controllers/JobdeskController.php | 4 +- app/Http/Controllers/OrderController.php | 246 +++++++++++++++++- app/Http/Controllers/ProductController.php | 24 +- app/Models/Product.php | 4 +- .../0001_01_01_000000_create_users_table.php | 4 +- .../2024_11_06_033508_create_orders_table.php | 5 +- ...024_11_23_124844_create_jobdesks_table.php | 3 +- 8 files changed, 272 insertions(+), 24 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 8765cee..045b69f 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -100,13 +100,7 @@ public function update(Request $request, Customer $customer) */ public function destroy(Customer $customer) { - $customer = Customer::find($customer->id); - foreach ($customer->orders as $order) { - $order->jobdesks()->delete(); // Pastikan ada relasi jobdesks() di model Order - } - $customer->orders()->delete(); $customer->delete(); - return response()->json($customer); } } diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 3a25a6c..9e94951 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -19,7 +19,9 @@ public function index(Request $request) // Filter by order_id if provided if ($orderId) { - $query->where('order_id', $orderId); + $query->whereHas('order', function ($query) use ($orderId) { + $query->where('id', $orderId); + }); } // Filter by status if provided diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index af9fcbf..89c918f 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -17,7 +17,7 @@ class OrderController extends Controller 'order_date' => 'required', 'product_id' => 'required', 'price' => 'required', - 'paid' => 'required', + 'paid' => 'nullable', 'payment_method' => 'required', 'data' => 'nullable', 'customer_id' => 'required|exists:customers,id', @@ -76,6 +76,248 @@ public function index(Request $request) // Paginate results $orders = $query->paginate(25); } + // { + // "current_page": 1, + // "data": [ + // { + // "id": 85, + // "no_order": "AN00085", + // "customer_id": "29", + // "order_date": "2025-01-23", + // "product_id": "22", + // "price": 100000, + // "payment_method": "Tunai", + // "paid": 50000, + // "data": [], + // "lampiran": null, + // "created_at": "2025-01-23T06:30:49.000000Z", + // "updated_at": "2025-01-24T07:37:35.000000Z", + // "customer": { + // "id": 29, + // "name": "Aditya Kristyanto", + // "phone": "087715567339", + // "alamat": "Tunggul, Jarum, Bayat", + // "created_at": "2025-01-23T06:21:08.000000Z", + // "updated_at": "2025-01-24T05:59:50.000000Z" + // }, + // "jobdesks": [], + // "product": { + // "id": 22, + // "name": "BPRS Madina Mandiri", + // "price": "4761810", + // "category": "bank", + // "description": "-", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z", + // "data_products": [] + // } + // }, + // { + // "id": 84, + // "no_order": "AN00084", + // "customer_id": "3", + // "order_date": "2025-01-23", + // "product_id": "22", + // "price": 100000, + // "payment_method": "Tunai", + // "paid": null, + // "data": [], + // "lampiran": null, + // "created_at": "2025-01-23T06:20:44.000000Z", + // "updated_at": "2025-01-24T06:48:29.000000Z", + // "customer": { + // "id": 3, + // "name": "Patricia Yuliarti", + // "phone": "0460 7975 746", + // "alamat": "Ds. Ir. H. Juanda No. 315, Salatiga 95933, Jambi", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // }, + // "jobdesks": [], + // "product": { + // "id": 22, + // "name": "BPRS Madina Mandiri", + // "price": "4761810", + // "category": "bank", + // "description": "-", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z", + // "data_products": [] + // } + // }, + // { + // "id": 62, + // "no_order": "AN00062", + // "customer_id": "22", + // "order_date": "2025-01-22", + // "product_id": "1", + // "price": 7428569, + // "payment_method": "Tunai", + // "paid": 5070730, + // "data": null, + // "lampiran": null, + // "created_at": "2025-01-23T03:28:39.000000Z", + // "updated_at": "2025-01-24T06:55:03.000000Z", + // "customer": { + // "id": 22, + // "name": "Iriana Palastri", + // "phone": "(+62) 936 4097 394", + // "alamat": "Dk. Flores No. 674, Semarang 83218, Sumsel", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // }, + // "jobdesks": [ + // { + // "id": 211, + // "order_id": "62", + // "deskripsi": "Saepe inventore qui beatae.", + // "user_id": "6", + // "tanggal_pengerjaan": "2025-01-14", + // "tanggal_selesai": "2025-01-23", + // "status": "Selesai", + // "created_at": "2025-01-23T03:28:39.000000Z", + // "updated_at": "2025-01-23T03:28:39.000000Z" + // }, + // { + // "id": 212, + // "order_id": "62", + // "deskripsi": "Qui magni et natus omnis labore.", + // "user_id": "3", + // "tanggal_pengerjaan": "2025-01-17", + // "tanggal_selesai": "2025-01-23", + // "status": "Selesai", + // "created_at": "2025-01-23T03:28:39.000000Z", + // "updated_at": "2025-01-23T03:28:39.000000Z" + // }, + // { + // "id": 213, + // "order_id": "62", + // "deskripsi": "Quo voluptas numquam facilis est dignissimos.", + // "user_id": "6", + // "tanggal_pengerjaan": "2025-01-16", + // "tanggal_selesai": null, + // "status": "Progress", + // "created_at": "2025-01-23T03:28:39.000000Z", + // "updated_at": "2025-01-23T03:28:39.000000Z" + // }, + // { + // "id": 214, + // "order_id": "62", + // "deskripsi": "Enim quia neque repudiandae consequatur.", + // "user_id": "6", + // "tanggal_pengerjaan": "2025-01-18", + // "tanggal_selesai": null, + // "status": "Progress", + // "created_at": "2025-01-23T03:28:39.000000Z", + // "updated_at": "2025-01-23T03:28:39.000000Z" + // } + // ], + // "product": { + // "id": 1, + // "name": "Perjanjian Kredit", + // "price": "600000", + // "category": "perorangan", + // "description": "-", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data_products": [ + // { + // "id": 157, + // "data_id": 1, + // "product_id": 1, + // "created_at": "2025-01-24T04:14:36.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data": { + // "id": 1, + // "name": "Judul Akta", + // "type": "text", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // } + // }, + // { + // "id": 158, + // "data_id": 2, + // "product_id": 1, + // "created_at": "2025-01-24T04:14:36.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data": { + // "id": 2, + // "name": "Nomor Akta", + // "type": "text", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // } + // }, + // { + // "id": 159, + // "data_id": 3, + // "product_id": 1, + // "created_at": "2025-01-24T04:14:36.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data": { + // "id": 3, + // "name": "Tanggal Akta", + // "type": "date", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // } + // }, + // { + // "id": 160, + // "data_id": 4, + // "product_id": 1, + // "created_at": "2025-01-24T04:14:36.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data": { + // "id": 4, + // "name": "Yang Mengerjakan", + // "type": "text", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // } + // }, + // { + // "id": 161, + // "data_id": 5, + // "product_id": 1, + // "created_at": "2025-01-24T04:14:36.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data": { + // "id": 5, + // "name": "Jumlah Pinjaman", + // "type": "number", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // } + // }, + // { + // "id": 162, + // "data_id": 6, + // "product_id": 1, + // "created_at": "2025-01-24T04:14:36.000000Z", + // "updated_at": "2025-01-24T04:14:36.000000Z", + // "data": { + // "id": 6, + // "name": "Lain-lain", + // "type": "text", + // "created_at": "2025-01-23T03:28:38.000000Z", + // "updated_at": "2025-01-23T03:28:38.000000Z" + // } + // } + // ] + // } + // }, + // $orders->getCollection()->transform(function ($data) { + // return [ + // 'id' => $data->id, + // 'no_order' => $data->no_order, + // 'customer_id' => $data->customer->id, + // 'order_date' => $data->order_date, + // 'product_id' => $data->product->id, + // 'price' => $data->price, + // ]; + // }); return response()->json($orders); } @@ -145,8 +387,6 @@ public function store(Request $request) public function destroy(Order $order) { - $order = Order::find($order->id); - $order->jobdesks()->delete(); $order->delete(); return response()->json($order); } diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 4c8507a..dcdb2b8 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -12,29 +12,39 @@ class ProductController extends Controller */ public function index(Request $request) { - $page = $request->query('page'); + $paginate = $request->query('paginate'); $name = $request->query('name'); // Query dasar semua products - $query = Product::query(); - - $query->with('dataProducts.data'); + $query = Product::with('dataProducts.data', 'orders'); // Filter berdasarkan name jika ada if ($name && strlen($name) > 2) { $query->where('name', 'like', '%' . $name . '%'); } - // shorting descending + // Shorting descending $query->orderBy('created_at', 'desc'); // Paginate the results - if ($page === 'all') { + if ($paginate === 'false') { $products = $query->get(); } else { $products = $query->paginate(25); } + // Transformasi data untuk response + $products->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'price' => $data->price, + 'description' => $data->description, + 'category' => $data->category, + 'data_products' => $data->dataProducts->pluck('data'), + 'order_count' => $data->orders->count(), + ]; + }); return response()->json($products); } @@ -84,7 +94,7 @@ public function update(Request $request, $id) 'data_products' => 'array|nullable', ]); - $product = Product::with('dataProducts.data')->findOrFail($id); + $product = Product::with('dataProducts.data', 'orders')->findOrFail($id); $product->update($request->only('name', 'price', 'description')); diff --git a/app/Models/Product.php b/app/Models/Product.php index d485dd3..34fffb3 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -22,8 +22,8 @@ public function dataProducts() return $this->hasMany(DataProduct::class, 'product_id'); } - public function order() + public function orders() { - return $this->belongsTo(Order::class); + return $this->hasMany(Order::class); } } diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index aea0992..cd186e1 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -27,13 +27,13 @@ public function up(): void }); Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email', 191)->primary(); // Use VARCHAR(191) + $table->string('email', 191)->primary(); $table->text('token'); $table->timestamp('created_at')->nullable(); }); Schema::create('sessions', function (Blueprint $table) { - $table->string('id', 191)->primary(); // Use VARCHAR(191) + $table->string('id', 191)->primary(); $table->unsignedBigInteger('user_id')->nullable(); $table->string('ip_address', 45)->nullable(); $table->text('user_agent')->nullable(); diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php index 91dd3e2..da18403 100644 --- a/database/migrations/2024_11_06_033508_create_orders_table.php +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -14,9 +14,10 @@ public function up(): void Schema::create('orders', function (Blueprint $table) { $table->id(); $table->string('no_order')->unique(); - $table->string('customer_id'); + $table->bigInteger('customer_id')->unsigned(); + $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade'); $table->date('order_date'); - $table->string('product_id'); + $table->bigInteger('product_id')->unsigned(); $table->integer('price')->nullable(); $table->string('payment_method')->nullable(); $table->integer('paid')->nullable(); diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2024_11_23_124844_create_jobdesks_table.php index f700e81..f72d0be 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2024_11_23_124844_create_jobdesks_table.php @@ -13,7 +13,8 @@ public function up(): void { Schema::create('jobdesks', function (Blueprint $table) { $table->id(); - $table->string('order_id'); + $table->bigInteger('product_id')->unsigned(); + $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); $table->text('deskripsi'); $table->string('user_id')->nullable(); $table->date('tanggal_pengerjaan')->nullable(); From 85f60111e717f3620c74e6ef1c27f9f4fdc2eabe Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 24 Jan 2025 19:22:36 +0700 Subject: [PATCH 089/184] Rename data to meta --- app/Http/Controllers/CustomerController.php | 18 +- app/Http/Controllers/JobdeskController.php | 2 +- ...{DataController.php => MetaController.php} | 12 +- app/Http/Controllers/OrderController.php | 226 ++---------------- app/Http/Controllers/ProductController.php | 31 ++- app/Http/Controllers/SettingController.php | 2 +- app/Models/Customer.php | 2 +- app/Models/JobDesk.php | 2 +- app/Models/{Data.php => Meta.php} | 8 +- .../{DataProduct.php => MetaProduct.php} | 12 +- app/Models/Product.php | 4 +- app/Notifications/NewOrderNotification.php | 4 +- app/Policies/DataPolicy.php | 14 +- database/factories/CustomerFactory.php | 2 +- database/factories/JobDeskFactory.php | 2 +- .../{DataFactory.php => MetaFactory.php} | 4 +- ...ductFactory.php => MetaProductFactory.php} | 10 +- ...24_11_01_021016_create_customers_table.php | 2 +- ...25_01_08_224039_create_jobdesks_table.php} | 8 +- ... 2025_01_08_231951_create_metas_table.php} | 4 +- ...1_09_074553_create_meta_product_table.php} | 6 +- database/seeders/DatabaseSeeder.php | 4 +- database/seeders/ProductSeeder.php | 68 +++--- routes/api.php | 4 +- 24 files changed, 135 insertions(+), 316 deletions(-) rename app/Http/Controllers/{DataController.php => MetaController.php} (77%) rename app/Models/{Data.php => Meta.php} (66%) rename app/Models/{DataProduct.php => MetaProduct.php} (73%) rename database/factories/{DataFactory.php => MetaFactory.php} (91%) rename database/factories/{DataProductFactory.php => MetaProductFactory.php} (72%) rename database/migrations/{2024_11_23_124844_create_jobdesks_table.php => 2025_01_08_224039_create_jobdesks_table.php} (72%) rename database/migrations/{2025_01_08_231951_create_data_table.php => 2025_01_08_231951_create_metas_table.php} (83%) rename database/migrations/{2025_01_09_074553_create_data_product_table.php => 2025_01_09_074553_create_meta_product_table.php} (75%) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 045b69f..920e045 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -14,7 +14,7 @@ class CustomerController extends Controller public $validate = [ 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20', - 'alamat' => 'required|string', + 'address' => 'required|string', ]; public function index(Request $request) @@ -42,7 +42,15 @@ public function index(Request $request) } else { $customers = $query->paginate(25); } - + $customers->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'phone' => $data->phone, + 'address' => $data->address, + 'order_count' => $data->orders->count(), + ]; + }); return response()->json($customers); } @@ -55,13 +63,13 @@ public function store(Request $request) [ 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20|unique:customers,phone', - 'alamat' => 'required|string', + 'address' => 'required|string', ], [ 'name.required' => 'Nama harus diisi.', 'phone.required' => 'Nomor telepon harus diisi.', 'phone.unique' => 'Nomor telepon sudah ada.', - 'alamat.required' => 'Alamat harus diisi.', + 'address.required' => 'Alamat harus diisi.', ] ); @@ -88,7 +96,7 @@ public function update(Request $request, Customer $customer) [ 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20|unique:customers,phone,' . $customer->id, - 'alamat' => 'required|string', + 'address' => 'required|string', ] ); $customer->update($validatedData); diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 9e94951..1e4f2d3 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -72,7 +72,7 @@ public function update(Request $request, Jobdesk $jobdesk) [ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', - 'deskripsi' => 'nullable', + 'description' => 'nullable', 'tanggal_pengerjaan' => 'nullable', 'tanggal_selesai' => 'nullable', 'status' => 'required', diff --git a/app/Http/Controllers/DataController.php b/app/Http/Controllers/MetaController.php similarity index 77% rename from app/Http/Controllers/DataController.php rename to app/Http/Controllers/MetaController.php index 0fc60f7..bc1367b 100644 --- a/app/Http/Controllers/DataController.php +++ b/app/Http/Controllers/MetaController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers; -use App\Models\Data; +use App\Models\Meta; use Illuminate\Http\Request; class DataController extends Controller @@ -15,9 +15,9 @@ public function index(Request $request) $paginate = $request->query('paginate'); if ($paginate === 'false') { - $data = Data::all(); + $data = Meta::all(); } else { - $data = Data::paginate(25); + $data = Meta::paginate(25); } return response()->json($data); } @@ -33,7 +33,7 @@ public function store(Request $request) /** * Display the specified resource. */ - public function show(Data $data) + public function show(Meta $data) { // } @@ -41,7 +41,7 @@ public function show(Data $data) /** * Update the specified resource in storage. */ - public function update(Request $request, Data $data) + public function update(Request $request, Meta $data) { // } @@ -49,7 +49,7 @@ public function update(Request $request, Data $data) /** * Remove the specified resource from storage. */ - public function destroy(Data $data) + public function destroy(Meta $data) { // } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 89c918f..ed0c0ef 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -96,7 +96,7 @@ public function index(Request $request) // "id": 29, // "name": "Aditya Kristyanto", // "phone": "087715567339", - // "alamat": "Tunggul, Jarum, Bayat", + // "address": "Tunggul, Jarum, Bayat", // "created_at": "2025-01-23T06:21:08.000000Z", // "updated_at": "2025-01-24T05:59:50.000000Z" // }, @@ -112,212 +112,24 @@ public function index(Request $request) // "data_products": [] // } // }, - // { - // "id": 84, - // "no_order": "AN00084", - // "customer_id": "3", - // "order_date": "2025-01-23", - // "product_id": "22", - // "price": 100000, - // "payment_method": "Tunai", - // "paid": null, - // "data": [], - // "lampiran": null, - // "created_at": "2025-01-23T06:20:44.000000Z", - // "updated_at": "2025-01-24T06:48:29.000000Z", - // "customer": { - // "id": 3, - // "name": "Patricia Yuliarti", - // "phone": "0460 7975 746", - // "alamat": "Ds. Ir. H. Juanda No. 315, Salatiga 95933, Jambi", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // }, - // "jobdesks": [], - // "product": { - // "id": 22, - // "name": "BPRS Madina Mandiri", - // "price": "4761810", - // "category": "bank", - // "description": "-", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z", - // "data_products": [] - // } - // }, - // { - // "id": 62, - // "no_order": "AN00062", - // "customer_id": "22", - // "order_date": "2025-01-22", - // "product_id": "1", - // "price": 7428569, - // "payment_method": "Tunai", - // "paid": 5070730, - // "data": null, - // "lampiran": null, - // "created_at": "2025-01-23T03:28:39.000000Z", - // "updated_at": "2025-01-24T06:55:03.000000Z", - // "customer": { - // "id": 22, - // "name": "Iriana Palastri", - // "phone": "(+62) 936 4097 394", - // "alamat": "Dk. Flores No. 674, Semarang 83218, Sumsel", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // }, - // "jobdesks": [ - // { - // "id": 211, - // "order_id": "62", - // "deskripsi": "Saepe inventore qui beatae.", - // "user_id": "6", - // "tanggal_pengerjaan": "2025-01-14", - // "tanggal_selesai": "2025-01-23", - // "status": "Selesai", - // "created_at": "2025-01-23T03:28:39.000000Z", - // "updated_at": "2025-01-23T03:28:39.000000Z" - // }, - // { - // "id": 212, - // "order_id": "62", - // "deskripsi": "Qui magni et natus omnis labore.", - // "user_id": "3", - // "tanggal_pengerjaan": "2025-01-17", - // "tanggal_selesai": "2025-01-23", - // "status": "Selesai", - // "created_at": "2025-01-23T03:28:39.000000Z", - // "updated_at": "2025-01-23T03:28:39.000000Z" - // }, - // { - // "id": 213, - // "order_id": "62", - // "deskripsi": "Quo voluptas numquam facilis est dignissimos.", - // "user_id": "6", - // "tanggal_pengerjaan": "2025-01-16", - // "tanggal_selesai": null, - // "status": "Progress", - // "created_at": "2025-01-23T03:28:39.000000Z", - // "updated_at": "2025-01-23T03:28:39.000000Z" - // }, - // { - // "id": 214, - // "order_id": "62", - // "deskripsi": "Enim quia neque repudiandae consequatur.", - // "user_id": "6", - // "tanggal_pengerjaan": "2025-01-18", - // "tanggal_selesai": null, - // "status": "Progress", - // "created_at": "2025-01-23T03:28:39.000000Z", - // "updated_at": "2025-01-23T03:28:39.000000Z" - // } - // ], - // "product": { - // "id": 1, - // "name": "Perjanjian Kredit", - // "price": "600000", - // "category": "perorangan", - // "description": "-", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data_products": [ - // { - // "id": 157, - // "data_id": 1, - // "product_id": 1, - // "created_at": "2025-01-24T04:14:36.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data": { - // "id": 1, - // "name": "Judul Akta", - // "type": "text", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // } - // }, - // { - // "id": 158, - // "data_id": 2, - // "product_id": 1, - // "created_at": "2025-01-24T04:14:36.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data": { - // "id": 2, - // "name": "Nomor Akta", - // "type": "text", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // } - // }, - // { - // "id": 159, - // "data_id": 3, - // "product_id": 1, - // "created_at": "2025-01-24T04:14:36.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data": { - // "id": 3, - // "name": "Tanggal Akta", - // "type": "date", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // } - // }, - // { - // "id": 160, - // "data_id": 4, - // "product_id": 1, - // "created_at": "2025-01-24T04:14:36.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data": { - // "id": 4, - // "name": "Yang Mengerjakan", - // "type": "text", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // } - // }, - // { - // "id": 161, - // "data_id": 5, - // "product_id": 1, - // "created_at": "2025-01-24T04:14:36.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data": { - // "id": 5, - // "name": "Jumlah Pinjaman", - // "type": "number", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // } - // }, - // { - // "id": 162, - // "data_id": 6, - // "product_id": 1, - // "created_at": "2025-01-24T04:14:36.000000Z", - // "updated_at": "2025-01-24T04:14:36.000000Z", - // "data": { - // "id": 6, - // "name": "Lain-lain", - // "type": "text", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z" - // } - // } - // ] - // } - // }, - // $orders->getCollection()->transform(function ($data) { - // return [ - // 'id' => $data->id, - // 'no_order' => $data->no_order, - // 'customer_id' => $data->customer->id, - // 'order_date' => $data->order_date, - // 'product_id' => $data->product->id, - // 'price' => $data->price, - // ]; - // }); + $orders->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'no_order' => $data->no_order, + 'customer_id' => $data->customer->id, + 'order_date' => $data->order_date, + 'product_id' => $data->product->id, + 'price' => $data->price, + 'payment_method' => $data->payment_method, + 'paid' => $data->paid, + 'data' => $data->data, + 'lampiran' => $data->lampiran, + 'jobdesk_count' => $data->jobdesks()->count(), + 'customer' => $data->customer, + 'jobdesks' => $data->jobdesks, + 'product' => $data->product + ]; + }); return response()->json($orders); } diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index dcdb2b8..5ca6a6b 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -16,7 +16,7 @@ public function index(Request $request) $name = $request->query('name'); // Query dasar semua products - $query = Product::with('dataProducts.data', 'orders'); + $query = Product::with('metaProducts.meta', 'orders'); // Filter berdasarkan name jika ada if ($name && strlen($name) > 2) { @@ -41,7 +41,7 @@ public function index(Request $request) 'price' => $data->price, 'description' => $data->description, 'category' => $data->category, - 'data_products' => $data->dataProducts->pluck('data'), + 'meta_id' => $data->metaProducts->pluck('data'), 'order_count' => $data->orders->count(), ]; }); @@ -58,15 +58,14 @@ public function store(Request $request) 'name' => 'string|max:255|nullable', 'price' => 'numeric|nullable', 'description' => 'string|nullable', - 'data_products' => 'array|nullable', + 'meta_products' => 'array|nullable', ]); $product = Product::create($request->only('name', 'price', 'description')); - // Simpan data_products - if ($request->has('data_products')) { - foreach ($request->input('data_products') as $dataId) { - $product->dataProducts()->create(['data_id' => $dataId]); + if ($request->has('meta_products')) { + foreach ($request->input('meta_products') as $metaId) { + $product->metaProducts()->create(['meta_id' => $metaId]); } } @@ -91,18 +90,18 @@ public function update(Request $request, $id) 'name' => 'string|max:255|nullable', 'price' => 'numeric|nullable', 'description' => 'string|nullable', - 'data_products' => 'array|nullable', + 'meta_id' => 'array|nullable', ]); - $product = Product::with('dataProducts.data', 'orders')->findOrFail($id); + $product = Product::with('metaProducts.meta', 'orders')->findOrFail($id); $product->update($request->only('name', 'price', 'description')); - // Update data_products - if ($request->has('data_products')) { - $product->dataProducts()->delete(); - foreach ($request->input('data_products') as $dataId) { - $product->dataProducts()->create(['data_id' => $dataId]); + // Update meta_id + if ($request->has('meta_products')) { + $product->metaProducts()->delete(); + foreach ($request->input('meta_products') as $metaId) { + $product->metaProducts()->create(['meta_id' => $metaId]); } } @@ -117,8 +116,8 @@ public function destroy($id) $product = Product::findOrFail($id); $product->delete(); - // hapus data_products - $product->dataProducts()->delete(); + // hapus meta_id + $product->metaProducts()->delete(); return response()->json(null, 204); } diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index 2bf5733..f489fdc 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -102,7 +102,7 @@ protected function validationRules() return [ 'app_name' => 'nullable|string|max:255', 'app_description' => 'nullable|string|max:500', - 'alamat' => 'nullable|string|max:255', + 'address' => 'nullable|string|max:255', 'banks' => 'nullable|string|max:2000', 'pekerjaan' => 'nullable|string|max:10000', 'pdf_sample' => 'nullable', diff --git a/app/Models/Customer.php b/app/Models/Customer.php index d84a0cf..abe344b 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -12,7 +12,7 @@ class Customer extends Model protected $fillable = [ 'name', 'phone', - 'alamat', + 'address', ]; public function orders() diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php index f6fad9f..64ce0c6 100644 --- a/app/Models/JobDesk.php +++ b/app/Models/JobDesk.php @@ -11,7 +11,7 @@ class Jobdesk extends Model protected $fillable = [ 'order_id', - 'deskripsi', + 'description', 'user_id', 'tanggal_pengerjaan', 'tanggal_selesai', diff --git a/app/Models/Data.php b/app/Models/Meta.php similarity index 66% rename from app/Models/Data.php rename to app/Models/Meta.php index d117149..fba0408 100644 --- a/app/Models/Data.php +++ b/app/Models/Meta.php @@ -5,21 +5,19 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class Data extends Model +class Meta extends Model { /** @use HasFactory<\Database\Factories\DataFactory> */ use HasFactory; - protected $table = 'data'; - protected $fillable = [ 'name', 'value', 'type' ]; - public function dataProducts() + public function metaProducts() { - return $this->hasMany(DataProduct::class, 'data_id'); + return $this->hasMany(MetaProduct::class, 'meta_id'); } } diff --git a/app/Models/DataProduct.php b/app/Models/MetaProduct.php similarity index 73% rename from app/Models/DataProduct.php rename to app/Models/MetaProduct.php index 89efd80..f97389a 100644 --- a/app/Models/DataProduct.php +++ b/app/Models/MetaProduct.php @@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -class DataProduct extends Model +class MetaProduct extends Model { use HasFactory; @@ -14,7 +14,7 @@ class DataProduct extends Model * * @var string */ - protected $table = 'data_product'; + protected $table = 'meta_product'; /** * The attributes that are mass assignable. @@ -22,16 +22,16 @@ class DataProduct extends Model * @var array */ protected $fillable = [ - 'data_id', + 'meta_id', 'product_id', ]; /** - * Get the related data. + * Get the related meta. */ - public function data() + public function meta() { - return $this->belongsTo(Data::class); + return $this->belongsTo(Meta::class); } /** diff --git a/app/Models/Product.php b/app/Models/Product.php index 34fffb3..716fa57 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -14,12 +14,12 @@ class Product extends Model 'price', 'description', 'category', - 'data', + 'meta', ]; public function dataProducts() { - return $this->hasMany(DataProduct::class, 'product_id'); + return $this->hasMany(MetaProduct::class, 'product_id'); } public function orders() diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index c5fd511..44fed89 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -35,7 +35,7 @@ public function __construct($order) '[nama_klien]', '[tanggal_order]', '[no_telp]', - '[alamat]', + '[address]', '[order_number]', '[product]', '[tim_manajemen]', @@ -44,7 +44,7 @@ public function __construct($order) $order->customer->name, $order->order_date, $order->customer->phone, - $order->customer->alamat, + $order->customer->address, $order->order_number, $order->product->name . ' (' . $order->product->category . ')', 'Tim Manajemen ' . Setting::where('setting_key', 'app_name')->value('setting_value'), diff --git a/app/Policies/DataPolicy.php b/app/Policies/DataPolicy.php index af2d80e..cc09249 100644 --- a/app/Policies/DataPolicy.php +++ b/app/Policies/DataPolicy.php @@ -2,11 +2,11 @@ namespace App\Policies; -use App\Models\Data; +use App\Models\Meta; use App\Models\User; use Illuminate\Auth\Access\Response; -class DataPolicy +class MetaPolicy { /** * Determine whether the user can view any models. @@ -19,7 +19,7 @@ public function viewAny(User $user): bool /** * Determine whether the user can view the model. */ - public function view(User $user, Data $data): bool + public function view(User $user, Meta $meta): bool { return false; } @@ -35,7 +35,7 @@ public function create(User $user): bool /** * Determine whether the user can update the model. */ - public function update(User $user, Data $data): bool + public function update(User $user, Meta $meta): bool { return false; } @@ -43,7 +43,7 @@ public function update(User $user, Data $data): bool /** * Determine whether the user can delete the model. */ - public function delete(User $user, Data $data): bool + public function delete(User $user, Meta $meta): bool { return false; } @@ -51,7 +51,7 @@ public function delete(User $user, Data $data): bool /** * Determine whether the user can restore the model. */ - public function restore(User $user, Data $data): bool + public function restore(User $user, Meta $meta): bool { return false; } @@ -59,7 +59,7 @@ public function restore(User $user, Data $data): bool /** * Determine whether the user can permanently delete the model. */ - public function forceDelete(User $user, Data $data): bool + public function forceDelete(User $user, Meta $meta): bool { return false; } diff --git a/database/factories/CustomerFactory.php b/database/factories/CustomerFactory.php index c83cdbd..70658e2 100644 --- a/database/factories/CustomerFactory.php +++ b/database/factories/CustomerFactory.php @@ -19,7 +19,7 @@ public function definition(): array return [ 'name' => fake()->name(), 'phone' => fake()->phoneNumber(), - 'alamat' => fake()->address(), + 'address' => fake()->address(), ]; } diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index fd41341..180c685 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -22,7 +22,7 @@ public function definition(): array return [ 'order_id' => fake()->numberBetween(1, 10), - 'deskripsi' => fake()->sentence(), + 'description' => fake()->sentence(), 'user_id' => $status !== 'Masuk' ? fake()->numberBetween(1, 10) : null, 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, 'tanggal_selesai' => $status === 'Selesai' ? now() : null, diff --git a/database/factories/DataFactory.php b/database/factories/MetaFactory.php similarity index 91% rename from database/factories/DataFactory.php rename to database/factories/MetaFactory.php index 0eb5c0c..5c7f916 100644 --- a/database/factories/DataFactory.php +++ b/database/factories/MetaFactory.php @@ -5,9 +5,9 @@ use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Data> + * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Meta> */ -class DataFactory extends Factory +class MetaFactory extends Factory { /** * Define the model's default state. diff --git a/database/factories/DataProductFactory.php b/database/factories/MetaProductFactory.php similarity index 72% rename from database/factories/DataProductFactory.php rename to database/factories/MetaProductFactory.php index 53c6bf4..3288536 100644 --- a/database/factories/DataProductFactory.php +++ b/database/factories/MetaProductFactory.php @@ -2,19 +2,19 @@ namespace Database\Factories; -use App\Models\DataProduct; -use App\Models\Data; +use App\Models\MetaProduct; +use App\Models\Meta; use App\Models\Product; use Illuminate\Database\Eloquent\Factories\Factory; -class DataProductFactory extends Factory +class MetaProductFactory extends Factory { /** * The name of the factory's corresponding model. * * @var string */ - protected $model = DataProduct::class; + protected $model = MetaProduct::class; /** * Define the model's default state. @@ -24,7 +24,7 @@ class DataProductFactory extends Factory public function definition() { return [ - 'data_id' => Data::factory(), + 'meta_id' => Meta::factory(), 'product_id' => Product::factory(), 'created_at' => now(), 'updated_at' => now(), diff --git a/database/migrations/2024_11_01_021016_create_customers_table.php b/database/migrations/2024_11_01_021016_create_customers_table.php index b68196b..9f13fb3 100644 --- a/database/migrations/2024_11_01_021016_create_customers_table.php +++ b/database/migrations/2024_11_01_021016_create_customers_table.php @@ -15,7 +15,7 @@ public function up(): void $table->id(); $table->string('name', 100); $table->string('phone', 20)->unique(); - $table->string('alamat', 255)->nullable(); + $table->string('address', 255)->nullable(); $table->timestamps(); }); } diff --git a/database/migrations/2024_11_23_124844_create_jobdesks_table.php b/database/migrations/2025_01_08_224039_create_jobdesks_table.php similarity index 72% rename from database/migrations/2024_11_23_124844_create_jobdesks_table.php rename to database/migrations/2025_01_08_224039_create_jobdesks_table.php index f72d0be..0a8b368 100644 --- a/database/migrations/2024_11_23_124844_create_jobdesks_table.php +++ b/database/migrations/2025_01_08_224039_create_jobdesks_table.php @@ -13,9 +13,11 @@ public function up(): void { Schema::create('jobdesks', function (Blueprint $table) { $table->id(); - $table->bigInteger('product_id')->unsigned(); - $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade'); - $table->text('deskripsi'); + $table->bigInteger('order_id')->unsigned()->nullable(); + $table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade'); + $table->bigInteger('product_id')->unsigned()->nullable(); + $table->foreign('product_id')->references('id')->on('products')->onDelete('set null'); + $table->text('description'); $table->string('user_id')->nullable(); $table->date('tanggal_pengerjaan')->nullable(); $table->date('tanggal_selesai')->nullable(); diff --git a/database/migrations/2025_01_08_231951_create_data_table.php b/database/migrations/2025_01_08_231951_create_metas_table.php similarity index 83% rename from database/migrations/2025_01_08_231951_create_data_table.php rename to database/migrations/2025_01_08_231951_create_metas_table.php index b8724eb..c08893a 100644 --- a/database/migrations/2025_01_08_231951_create_data_table.php +++ b/database/migrations/2025_01_08_231951_create_metas_table.php @@ -11,7 +11,7 @@ */ public function up(): void { - Schema::create('data', function (Blueprint $table) { + Schema::create('metas', function (Blueprint $table) { $table->id(); $table->string('name'); $table->string('type'); @@ -24,6 +24,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('data'); + Schema::dropIfExists('metas'); } }; diff --git a/database/migrations/2025_01_09_074553_create_data_product_table.php b/database/migrations/2025_01_09_074553_create_meta_product_table.php similarity index 75% rename from database/migrations/2025_01_09_074553_create_data_product_table.php rename to database/migrations/2025_01_09_074553_create_meta_product_table.php index d3ae22f..7839b95 100644 --- a/database/migrations/2025_01_09_074553_create_data_product_table.php +++ b/database/migrations/2025_01_09_074553_create_meta_product_table.php @@ -11,9 +11,9 @@ */ public function up(): void { - Schema::create('data_product', function (Blueprint $table) { + Schema::create('meta_product', function (Blueprint $table) { $table->id(); - $table->foreignId('data_id')->constrained()->onDelete('cascade'); + $table->foreignId('meta_id')->constrained()->onDelete('cascade'); $table->foreignId('product_id')->constrained()->onDelete('cascade'); $table->timestamps(); }); @@ -24,6 +24,6 @@ public function up(): void */ public function down(): void { - Schema::dropIfExists('data_product'); + Schema::dropIfExists('meta_product'); } }; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d9cac5a..6a28526 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -61,7 +61,7 @@ protected function seedSettings() Detail Proyek:
======================================
Nama Proyek: [nama_proyek]
- Deskripsi: [deskripsi_proyek]
+ Deskripsi: [description_proyek]
Batas Waktu: [batas_waktu]
Penanggung Jawab: [nama_superadmin]
======================================
@@ -97,7 +97,7 @@ protected function seedSettings() ['setting_key' => 'app_name', 'setting_value' => 'APP'], ['setting_key' => 'app_code', 'setting_value' => 'AN'], ['setting_key' => 'app_description', 'setting_value' => 'Asisten Notaris Online'], - ['setting_key' => 'alamat', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], + ['setting_key' => 'address', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], ['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf'], ['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com'], ]; diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index 5030366..856fbc0 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -4,8 +4,8 @@ use Illuminate\Database\Seeder; use App\Models\Product; -use App\Models\Data; -use App\Models\DataProduct; +use App\Models\Meta; +use App\Models\MetaProduct; class ProductSeeder extends Seeder { @@ -17,122 +17,122 @@ public function run(): void $products = [ 'perjanjian_kredit' => [ 'title' => 'Perjanjian Kredit', - 'data' => [1, 2, 3, 4, 5, 6], + 'meta' => [1, 2, 3, 4, 5, 6], 'category' => 'perorangan' ], 'skmht' => [ 'title' => 'SKMHT', - 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14, 7], + 'meta' => [2, 3, 8, 9, 10, 11, 12, 13, 14, 7], 'category' => 'perorangan' ], 'apht' => [ 'title' => 'APHT', - 'data' => [2, 3, 8, 9, 10, 11, 12, 13, 14], + 'meta' => [2, 3, 8, 9, 10, 11, 12, 13, 14], 'category' => 'perorangan' ], 'fidusia' => [ 'title' => 'Fidusia', - 'data' => [2, 3, 15, 16, 17, 18, 19, 20, 21, 7], + 'meta' => [2, 3, 15, 16, 17, 18, 19, 20, 21, 7], 'category' => 'perorangan' ], 'jual_beli' => [ 'title' => 'Jual Beli', - 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'meta' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], 'category' => 'perorangan', ], 'hibah' => [ 'title' => 'Hibah', - 'data' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'meta' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], 'category' => 'perorangan', ], 'turun_waris' => [ 'title' => 'Turun Waris', - 'data' => [22, 23, 24, 25, 26, 27, 28, 29, 30], + 'meta' => [22, 23, 24, 25, 26, 27, 28, 29, 30], 'category' => 'perorangan', ], 'pecah' => [ 'title' => 'Pecah', - 'data' => [1, 44], + 'meta' => [1, 44], 'category' => 'perorangan', ], 'pendirian_pt' => [ 'title' => 'Pendirian PT', - 'data' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], 'category' => 'perorangan', ], 'pendirian_cv' => [ 'title' => 'Pendirian CV', - 'data' => [1, 2, 3, 46, 47, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 46, 47, 21, 45, 41, 52], 'category' => 'perorangan', ], 'pendirian_yayasan' => [ 'title' => 'Pendirian Yayasan', - 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'meta' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], 'category' => 'perorangan', ], 'pendirian_pt_perseorangan' => [ 'title' => 'Pendirian PT Perseorangan', - 'data' => [1, 2, 3, 42, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 21, 45, 41, 52], 'category' => 'perorangan', ], 'perubahan_pt' => [ 'title' => 'Perubahan PT', - 'data' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], 'category' => 'perorangan', ], 'perubahan_cv' => [ 'title' => 'Perubahan CV', - 'data' => [1, 2, 3, 46, 47, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 46, 47, 21, 45, 41, 52], 'category' => 'perorangan', ], 'perubahan_yayasan' => [ 'title' => 'Perubahan Yayasan', - 'data' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'meta' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], 'category' => 'perorangan', ], 'perubahan_pt_perseorangan' => [ 'title' => 'Perubahan PT Perseorangan', - 'data' => [1, 2, 3, 42, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 21, 45, 41, 52], 'category' => 'perorangan', ], // BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat' 'bpr_bba' => [ 'title' => 'BPR BBA', - 'data' => [], + 'meta' => [], 'category' => 'bank', ], 'bpr_pala_pusat' => [ 'title' => 'BPR Pala Pusat', - 'data' => [], + 'meta' => [], 'category' => 'bank', ], 'bpr_pala_cabang' => [ 'title' => 'BPR Pala Cabang', - 'data' => [], + 'meta' => [], 'category' => 'bank', ], 'bpr_danamas_prime' => [ 'title' => 'BPR Danamas Prime', - 'data' => [], + 'meta' => [], 'category' => 'bank', ], 'bpr_arum_mandiri' => [ 'title' => 'BPR Arum Mandiri', - 'data' => [], + 'meta' => [], 'category' => 'bank', ], 'bprs_madina_mandiri' => [ 'title' => 'BPRS Madina Mandiri', - 'data' => [], + 'meta' => [], 'category' => 'bank', ], 'bmt_sejahtera_ummat' => [ 'title' => 'BMT Sejahtera Ummat', - 'data' => [], + 'meta' => [], 'category' => 'bank', ] ]; - $datas = [ + $metas = [ 1 => [ 'title' => 'Judul Akta', 'type' => 'text' @@ -345,15 +345,15 @@ public function run(): void // Membuat 5 customer - foreach ($datas as $id => $data) { - Data::factory()->create([ + foreach ($metas as $id => $meta) { + Meta::factory()->create([ 'id' => $id, - 'name' => $data['title'], - 'type' => $data['type'] + 'name' => $meta['title'], + 'type' => $meta['type'] ]); } - // Insert data ke tabel 'products' dan 'data_product' + // Insert meta ke tabel 'products' dan 'meta_product' foreach ($products as $slug => $product) { $productId = Product::factory()->create([ 'name' => $product['title'], @@ -361,9 +361,9 @@ public function run(): void 'category' => $product['category'] ]); - foreach ($product['data'] as $dataId) { - DataProduct::factory()->create([ - 'data_id' => $dataId, + foreach ($product['meta'] as $metaId) { + MetaProduct::factory()->create([ + 'meta_id' => $metaId, 'product_id' => $productId ]); } diff --git a/routes/api.php b/routes/api.php index 5f267c4..d2a85be 100644 --- a/routes/api.php +++ b/routes/api.php @@ -10,7 +10,7 @@ use App\Http\Controllers\SettingController; use App\Http\Controllers\UserController; use App\Http\Controllers\ProductController; -use App\Http\Controllers\DataController; +use App\Http\Controllers\MetaController; use App\Http\Controllers\SendNotificationController; use App\Http\Controllers\Auth\ProfileController; use App\Http\Controllers\NotificationController; @@ -33,6 +33,6 @@ 'customers' => CustomerController::class, 'settings' => SettingController::class, 'products' => ProductController::class, - 'data' => DataController::class + 'meta' => MetaController::class ]); }); From 3aea0d54876bd60fa8fa2a3e1a9801c83ba1ef67 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 24 Jan 2025 23:14:22 +0700 Subject: [PATCH 090/184] fix order controller --- app/Http/Controllers/OrderController.php | 72 ++++++++----------- app/Http/Controllers/ProductController.php | 2 +- app/Models/Order.php | 4 +- app/Models/Product.php | 2 +- database/factories/OrderFactory.php | 2 +- .../2024_11_06_033508_create_orders_table.php | 2 +- 6 files changed, 35 insertions(+), 49 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index ed0c0ef..49ac0ee 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -19,7 +19,7 @@ class OrderController extends Controller 'price' => 'required', 'paid' => 'nullable', 'payment_method' => 'required', - 'data' => 'nullable', + 'meta' => 'nullable', 'customer_id' => 'required|exists:customers,id', ]; public function index(Request $request) @@ -31,7 +31,7 @@ public function index(Request $request) $status = $request->query('status'); $status = isset($status) ? $status : null; - $query = Order::with('customer', 'jobdesks', 'product', 'product.dataProducts.data'); + $query = Order::with('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); if ($customerId) { $query->where('customer_id', $customerId); @@ -76,42 +76,6 @@ public function index(Request $request) // Paginate results $orders = $query->paginate(25); } - // { - // "current_page": 1, - // "data": [ - // { - // "id": 85, - // "no_order": "AN00085", - // "customer_id": "29", - // "order_date": "2025-01-23", - // "product_id": "22", - // "price": 100000, - // "payment_method": "Tunai", - // "paid": 50000, - // "data": [], - // "lampiran": null, - // "created_at": "2025-01-23T06:30:49.000000Z", - // "updated_at": "2025-01-24T07:37:35.000000Z", - // "customer": { - // "id": 29, - // "name": "Aditya Kristyanto", - // "phone": "087715567339", - // "address": "Tunggul, Jarum, Bayat", - // "created_at": "2025-01-23T06:21:08.000000Z", - // "updated_at": "2025-01-24T05:59:50.000000Z" - // }, - // "jobdesks": [], - // "product": { - // "id": 22, - // "name": "BPRS Madina Mandiri", - // "price": "4761810", - // "category": "bank", - // "description": "-", - // "created_at": "2025-01-23T03:28:38.000000Z", - // "updated_at": "2025-01-23T03:28:38.000000Z", - // "data_products": [] - // } - // }, $orders->getCollection()->transform(function ($data) { return [ 'id' => $data->id, @@ -122,12 +86,24 @@ public function index(Request $request) 'price' => $data->price, 'payment_method' => $data->payment_method, 'paid' => $data->paid, - 'data' => $data->data, + 'meta' => $data->meta, 'lampiran' => $data->lampiran, 'jobdesk_count' => $data->jobdesks()->count(), - 'customer' => $data->customer, + 'customer' => [ + 'id' => $data->customer->id, + 'name' => $data->customer->name, + 'phone' => $data->customer->phone, + 'address' => $data->customer->address, + ], 'jobdesks' => $data->jobdesks, - 'product' => $data->product + 'product' => [ + 'id' => $data->product->id, + 'name' => $data->product->name, + 'price' => $data->product->price, + 'category' => $data->product->category, + 'description' => $data->product->description, + 'meta_products' => $data->product->metaProducts->pluck('meta'), + ] ]; }); @@ -152,7 +128,17 @@ public function update(Request $request, Order $order) } // Validasi data yang diterima - $validatedData = $request->validate($this->validate); + $validatedData = $request->validate( + [ + 'order_date' => 'required', + 'product_id' => 'required', + 'price' => 'required', + 'paid' => 'nullable', + 'payment_method' => 'required', + 'meta' => 'nullable', + 'customer_id' => 'required|exists:customers,id', + ] + ); // Validasi dokumen jika ada if ($request->hasFile('lampiran')) { @@ -180,7 +166,7 @@ public function store(Request $request) 'price' => 'required', 'paid' => 'required', 'payment_method' => 'required', - 'data' => 'nullable', + 'meta' => 'nullable', 'customer_id' => 'required|exists:customers,id', ]); diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 5ca6a6b..a01fbb4 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -41,7 +41,7 @@ public function index(Request $request) 'price' => $data->price, 'description' => $data->description, 'category' => $data->category, - 'meta_id' => $data->metaProducts->pluck('data'), + 'meta' => $data->metaProducts->pluck('meta'), 'order_count' => $data->orders->count(), ]; }); diff --git a/app/Models/Order.php b/app/Models/Order.php index 85600f9..399902a 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -47,12 +47,12 @@ protected static function boot() 'price', 'payment_method', 'paid', - 'data', + 'meta', 'lampiran', ]; protected $casts = [ - 'data' => 'array', + 'meta' => 'array', ]; public function customer() diff --git a/app/Models/Product.php b/app/Models/Product.php index 716fa57..69e4f98 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -17,7 +17,7 @@ class Product extends Model 'meta', ]; - public function dataProducts() + public function metaProducts() { return $this->hasMany(MetaProduct::class, 'product_id'); } diff --git a/database/factories/OrderFactory.php b/database/factories/OrderFactory.php index 06314f1..f41ffee 100644 --- a/database/factories/OrderFactory.php +++ b/database/factories/OrderFactory.php @@ -26,7 +26,7 @@ public function definition(): array 'price' => $price, 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), 'paid' => $paid, - 'data' => null, + 'meta' => null, ]; } } diff --git a/database/migrations/2024_11_06_033508_create_orders_table.php b/database/migrations/2024_11_06_033508_create_orders_table.php index da18403..76d08ef 100644 --- a/database/migrations/2024_11_06_033508_create_orders_table.php +++ b/database/migrations/2024_11_06_033508_create_orders_table.php @@ -21,7 +21,7 @@ public function up(): void $table->integer('price')->nullable(); $table->string('payment_method')->nullable(); $table->integer('paid')->nullable(); - $table->text('data')->nullable(); + $table->text('meta')->nullable(); $table->text('lampiran')->nullable(); $table->timestamps(); }); From c2d054f276de3c107d65eeab212e4c04c4ac7279 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 25 Jan 2025 14:38:05 +0700 Subject: [PATCH 091/184] fix product controller --- app/Http/Controllers/CustomerController.php | 30 +++-- app/Http/Controllers/MetaController.php | 14 +-- app/Http/Controllers/OrderController.php | 133 ++++++++++++-------- app/Http/Controllers/ProductController.php | 39 +++--- app/Models/Product.php | 1 - database/seeders/ProductSeeder.php | 2 +- 6 files changed, 135 insertions(+), 84 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 920e045..e32cf7d 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -38,19 +38,29 @@ public function index(Request $request) $query->orderBy('created_at', 'desc'); if ($paginate === 'false') { - $customers = $query->get(); + $customers = $query->get()->map(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'phone' => $data->phone, + 'address' => $data->address, + 'order_count' => $data->orders->count(), + 'orders' => $data->orders + ]; + }); } else { $customers = $query->paginate(25); + $customers->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'phone' => $data->phone, + 'address' => $data->address, + 'order_count' => $data->orders->count(), + 'orders' => $data->orders + ]; + }); } - $customers->getCollection()->transform(function ($data) { - return [ - 'id' => $data->id, - 'name' => $data->name, - 'phone' => $data->phone, - 'address' => $data->address, - 'order_count' => $data->orders->count(), - ]; - }); return response()->json($customers); } diff --git a/app/Http/Controllers/MetaController.php b/app/Http/Controllers/MetaController.php index bc1367b..4e80863 100644 --- a/app/Http/Controllers/MetaController.php +++ b/app/Http/Controllers/MetaController.php @@ -5,7 +5,7 @@ use App\Models\Meta; use Illuminate\Http\Request; -class DataController extends Controller +class MetaController extends Controller { /** * Display a listing of the resource. @@ -15,11 +15,11 @@ public function index(Request $request) $paginate = $request->query('paginate'); if ($paginate === 'false') { - $data = Meta::all(); + $meta = Meta::all(); } else { - $data = Meta::paginate(25); + $meta = Meta::paginate(25); } - return response()->json($data); + return response()->json($meta); } /** @@ -33,7 +33,7 @@ public function store(Request $request) /** * Display the specified resource. */ - public function show(Meta $data) + public function show(Meta $meta) { // } @@ -41,7 +41,7 @@ public function show(Meta $data) /** * Update the specified resource in storage. */ - public function update(Request $request, Meta $data) + public function update(Request $request, Meta $meta) { // } @@ -49,7 +49,7 @@ public function update(Request $request, Meta $data) /** * Remove the specified resource from storage. */ - public function destroy(Meta $data) + public function destroy(Meta $meta) { // } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 49ac0ee..69561e0 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -41,6 +41,23 @@ public function index(Request $request) $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); }); + } else { + if ($status) { + $query->whereDoesntHave('jobdesks', function ($query) use ($status) { + $query->where('status', '!=', 'Selesai'); + }); + if ($status === 'Selesai') { + $query->whereNotNull('lampiran'); + } + if ($status === 'Arsip') { + $query->whereNull('lampiran'); + } + $query->whereHas('jobdesks'); + } else if (!($customerId || $name)) { + $query->whereHas('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->orWhereDoesntHave('jobdesks'); + } } if ($product && strlen($product) > 2) { @@ -49,64 +66,77 @@ public function index(Request $request) }); } - if ($status) { - $query->whereDoesntHave('jobdesks', function ($query) use ($status) { - $query->where('status', '!=', 'Selesai'); - }); - if ($status === 'Selesai') { - $query->whereNotNull('lampiran'); - } - if ($status === 'Arsip') { - $query->whereNull('lampiran'); - } - $query->whereHas('jobdesks'); - } else if (!($customerId || $name)) { - $query->whereHas('jobdesks', function ($query) { - $query->where('status', '!=', 'Selesai'); - })->orWhereDoesntHave('jobdesks'); - } - $query->orderBy('created_at', 'desc'); // Check if pagination should be disabled if ($paginate === 'false') { // Get all records without pagination - $orders = $query->get(); + $orders = $query->get()->map(function ($data) { + return [ + 'id' => $data->id, + 'no_order' => $data->no_order, + 'customer_id' => $data->customer->id, + 'order_date' => $data->order_date, + 'product_id' => $data->product->id, + 'price' => $data->price, + 'payment_method' => $data->payment_method, + 'paid' => $data->paid, + 'meta' => $data->meta, + 'lampiran' => $data->lampiran, + 'jobdesk_count' => $data->jobdesks()->count(), + 'created_at' => $data->created_at, + 'customer' => [ + 'id' => $data->customer->id, + 'name' => $data->customer->name, + 'phone' => $data->customer->phone, + 'address' => $data->customer->address, + ], + 'jobdesks' => $data->jobdesks, + 'product' => [ + 'id' => $data->product->id, + 'name' => $data->product->name, + 'price' => $data->product->price, + 'category' => $data->product->category, + 'description' => $data->product->description, + 'meta_products' => $data->product->metaProducts->pluck('meta'), + ] + ]; + }); } else { // Paginate results $orders = $query->paginate(25); + $orders->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'no_order' => $data->no_order, + 'customer_id' => $data->customer->id, + 'order_date' => $data->order_date, + 'product_id' => $data->product->id, + 'price' => $data->price, + 'payment_method' => $data->payment_method, + 'paid' => $data->paid, + 'meta' => $data->meta, + 'lampiran' => $data->lampiran, + 'jobdesk_count' => $data->jobdesks()->count(), + 'created_at' => $data->created_at, + 'customer' => [ + 'id' => $data->customer->id, + 'name' => $data->customer->name, + 'phone' => $data->customer->phone, + 'address' => $data->customer->address, + ], + 'jobdesks' => $data->jobdesks, + 'product' => [ + 'id' => $data->product->id, + 'name' => $data->product->name, + 'price' => $data->product->price, + 'category' => $data->product->category, + 'description' => $data->product->description, + 'meta_products' => $data->product->metaProducts->pluck('meta'), + ] + ]; + }); } - $orders->getCollection()->transform(function ($data) { - return [ - 'id' => $data->id, - 'no_order' => $data->no_order, - 'customer_id' => $data->customer->id, - 'order_date' => $data->order_date, - 'product_id' => $data->product->id, - 'price' => $data->price, - 'payment_method' => $data->payment_method, - 'paid' => $data->paid, - 'meta' => $data->meta, - 'lampiran' => $data->lampiran, - 'jobdesk_count' => $data->jobdesks()->count(), - 'customer' => [ - 'id' => $data->customer->id, - 'name' => $data->customer->name, - 'phone' => $data->customer->phone, - 'address' => $data->customer->address, - ], - 'jobdesks' => $data->jobdesks, - 'product' => [ - 'id' => $data->product->id, - 'name' => $data->product->name, - 'price' => $data->product->price, - 'category' => $data->product->category, - 'description' => $data->product->description, - 'meta_products' => $data->product->metaProducts->pluck('meta'), - ] - ]; - }); - return response()->json($orders); } @@ -136,7 +166,7 @@ public function update(Request $request, Order $order) 'paid' => 'nullable', 'payment_method' => 'required', 'meta' => 'nullable', - 'customer_id' => 'required|exists:customers,id', + 'customer' => 'required', ] ); @@ -154,6 +184,7 @@ public function update(Request $request, Order $order) // Update order dengan data yang sudah divalidasi $order->update($validatedData); + $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); return response()->json($order); } @@ -178,6 +209,8 @@ public function store(Request $request) } $order = Order::create($validator->validated()); + $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); + $users = User::where('is_admin', 1)->orWhere('position', 'owner')->get(); Notification::send($users, new NewOrderNotification($order)); return response()->json($order); diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index a01fbb4..85323cc 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -28,24 +28,33 @@ public function index(Request $request) // Paginate the results if ($paginate === 'false') { - $products = $query->get(); + $products = $query->get()->map(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'price' => $data->price, + 'description' => $data->description, + 'category' => $data->category, + 'meta' => $data->metaProducts->pluck('meta')->pluck('id'), + 'meta_products' => $data->metaProducts->pluck('meta'), + 'order_count' => $data->orders->count(), + ]; + }); } else { $products = $query->paginate(25); + $products->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'price' => $data->price, + 'description' => $data->description, + 'category' => $data->category, + 'meta_products' => $data->metaProducts->pluck('meta')->pluck('id'), + 'order_count' => $data->orders->count(), + ]; + }); } - // Transformasi data untuk response - $products->getCollection()->transform(function ($data) { - return [ - 'id' => $data->id, - 'name' => $data->name, - 'price' => $data->price, - 'description' => $data->description, - 'category' => $data->category, - 'meta' => $data->metaProducts->pluck('meta'), - 'order_count' => $data->orders->count(), - ]; - }); - return response()->json($products); } @@ -104,7 +113,7 @@ public function update(Request $request, $id) $product->metaProducts()->create(['meta_id' => $metaId]); } } - + $product->load('metaProducts.meta', 'orders'); return response()->json($product); } diff --git a/app/Models/Product.php b/app/Models/Product.php index 69e4f98..9f0c0ea 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -14,7 +14,6 @@ class Product extends Model 'price', 'description', 'category', - 'meta', ]; public function metaProducts() diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index 856fbc0..dafac4e 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -349,7 +349,7 @@ public function run(): void Meta::factory()->create([ 'id' => $id, 'name' => $meta['title'], - 'type' => $meta['type'] + 'type' => $meta['type'], ]); } From 3c5970321d10e618eb30b35b2f00e9fa61f227b3 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 27 Jan 2025 18:30:51 +0700 Subject: [PATCH 092/184] fix response --- app/Http/Controllers/OrderController.php | 63 ++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 69561e0..787dadd 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -185,8 +185,36 @@ public function update(Request $request, Order $order) // Update order dengan data yang sudah divalidasi $order->update($validatedData); $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); - - return response()->json($order); + $response = [ + 'id' => $order->id, + 'no_order' => $order->no_order, + 'customer_id' => $order->customer->id, + 'order_date' => $order->order_date, + 'product_id' => $order->product->id, + 'price' => $order->price, + 'payment_method' => $order->payment_method, + 'paid' => $order->paid, + 'meta' => $order->meta, + 'lampiran' => $order->lampiran, + 'jobdesk_count' => $order->jobdesks()->count(), + 'created_at' => $order->created_at, + 'customer' => [ + 'id' => $order->customer->id, + 'name' => $order->customer->name, + 'phone' => $order->customer->phone, + 'address' => $order->customer->address, + ], + 'jobdesks' => $order->jobdesks, + 'product' => [ + 'id' => $order->product->id, + 'name' => $order->product->name, + 'price' => $order->product->price, + 'category' => $order->product->category, + 'description' => $order->product->description, + 'meta_products' => $order->product->metaProducts->pluck('meta'), + ] + ]; + return response()->json($response); } public function store(Request $request) @@ -213,7 +241,36 @@ public function store(Request $request) $users = User::where('is_admin', 1)->orWhere('position', 'owner')->get(); Notification::send($users, new NewOrderNotification($order)); - return response()->json($order); + $response = [ + 'id' => $order->id, + 'no_order' => $order->no_order, + 'customer_id' => $order->customer->id, + 'order_date' => $order->order_date, + 'product_id' => $order->product->id, + 'price' => $order->price, + 'payment_method' => $order->payment_method, + 'paid' => $order->paid, + 'meta' => $order->meta, + 'lampiran' => $order->lampiran, + 'jobdesk_count' => $order->jobdesks()->count(), + 'created_at' => $order->created_at, + 'customer' => [ + 'id' => $order->customer->id, + 'name' => $order->customer->name, + 'phone' => $order->customer->phone, + 'address' => $order->customer->address, + ], + 'jobdesks' => $order->jobdesks, + 'product' => [ + 'id' => $order->product->id, + 'name' => $order->product->name, + 'price' => $order->product->price, + 'category' => $order->product->category, + 'description' => $order->product->description, + 'meta_products' => $order->product->metaProducts->pluck('meta'), + ] + ]; + return response()->json($response); } public function destroy(Order $order) From 1114c2f1f7c15f0fc627571ff73f8270946e66b8 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 27 Jan 2025 21:15:37 +0700 Subject: [PATCH 093/184] fix jobdesk controller --- app/Http/Controllers/JobdeskController.php | 39 +++++++++++-------- app/Models/JobDesk.php | 11 +++++- ...025_01_08_224039_create_jobdesks_table.php | 11 +++--- 3 files changed, 38 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 1e4f2d3..3ee6d7c 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -48,23 +48,29 @@ public function index(Request $request) public function store(Request $request) { - $validatedData = $request->validate([ - 'order_id' => 'required|exists:orders,id', - 'user_id' => 'required|exists:users,id', - 'tanggal_pengerjaan' => 'nullable', - 'tanggal_selesai' => 'nullable', - 'status' => 'required', - ]); - if (isset($validatedData['tanggal_pengerjaan'])) { - $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); - } - if (isset($validatedData['tanggal_selesai'])) { - $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); + try { + $validatedData = $request->validate([ + 'order_id' => 'required|exists:orders,id', + 'user_id' => 'required|exists:users,id', + 'tanggal_pengerjaan' => 'nullable|date', + 'tanggal_selesai' => 'nullable|date', + 'status' => 'nullable|string', + ]); + + if (isset($validatedData['tanggal_pengerjaan'])) { + $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); + } + if (isset($validatedData['tanggal_selesai'])) { + $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); + } + $jobdesk = Jobdesk::create($validatedData); + // relation + $jobdesk->load('order', 'order.customer', 'user', 'order.product'); + return response()->json($jobdesk, 201); + } catch (\Exception $e) { + return response()->json(['message' => 'Server Error', 'error' => $e->getMessage()], 500); } - $jobdesk = Jobdesk::create($validatedData); - return response()->json($jobdesk); } - public function update(Request $request, Jobdesk $jobdesk) { $jobdesk = Jobdesk::find($jobdesk->id); @@ -91,12 +97,13 @@ public function update(Request $request, Jobdesk $jobdesk) $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); } $jobdesk->update($validatedData); + $jobdesk->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk); } public function show(Jobdesk $jobdesk) { - $jobdesk = Jobdesk::find($jobdesk->id)->load('customer', 'order', 'user'); + $jobdesk = Jobdesk::find($jobdesk->id)->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk); } diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php index 64ce0c6..3617dde 100644 --- a/app/Models/JobDesk.php +++ b/app/Models/JobDesk.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class Jobdesk extends Model { @@ -17,12 +18,18 @@ class Jobdesk extends Model 'tanggal_selesai', 'status', ]; - public function order() + + protected $casts = [ + 'tanggal_pengerjaan' => 'date', // Automatic casting to date + 'tanggal_selesai' => 'date', // Automatic casting to date + ]; + + public function order(): BelongsTo { return $this->belongsTo(Order::class); } - public function user() + public function user(): BelongsTo { return $this->belongsTo(User::class); } diff --git a/database/migrations/2025_01_08_224039_create_jobdesks_table.php b/database/migrations/2025_01_08_224039_create_jobdesks_table.php index 0a8b368..bb14992 100644 --- a/database/migrations/2025_01_08_224039_create_jobdesks_table.php +++ b/database/migrations/2025_01_08_224039_create_jobdesks_table.php @@ -13,12 +13,13 @@ public function up(): void { Schema::create('jobdesks', function (Blueprint $table) { $table->id(); - $table->bigInteger('order_id')->unsigned()->nullable(); + $table->unsignedBigInteger('order_id')->nullable(); $table->foreign('order_id')->references('id')->on('orders')->onDelete('cascade'); - $table->bigInteger('product_id')->unsigned()->nullable(); - $table->foreign('product_id')->references('id')->on('products')->onDelete('set null'); - $table->text('description'); - $table->string('user_id')->nullable(); + + $table->text('description')->nullable(); + $table->unsignedBigInteger('user_id')->nullable(); // Assuming it references the users table + $table->foreign('user_id')->references('id')->on('users')->onDelete('set null'); // Add foreign key constraint + $table->date('tanggal_pengerjaan')->nullable(); $table->date('tanggal_selesai')->nullable(); $table->string('status')->nullable(); From 8d71ae7a9e0d5c3f6dd95d1001f906b775244a05 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 13:19:03 +0700 Subject: [PATCH 094/184] fix jobdesk controller --- app/Http/Controllers/JobdeskController.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 3ee6d7c..a2c1714 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -19,9 +19,7 @@ public function index(Request $request) // Filter by order_id if provided if ($orderId) { - $query->whereHas('order', function ($query) use ($orderId) { - $query->where('id', $orderId); - }); + $query->where('order_id', $orderId); } // Filter by status if provided From e3468747ad10faeedef32eb64fa9a9c5046ed6cb Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 13:31:03 +0700 Subject: [PATCH 095/184] show all status --- app/Http/Controllers/JobdeskController.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index a2c1714..3bc3230 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -23,7 +23,7 @@ public function index(Request $request) } // Filter by status if provided - if ($status) { + if ($status && $status !== 'Masuk') { $query->where('status', $status); } @@ -50,6 +50,7 @@ public function store(Request $request) $validatedData = $request->validate([ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', + 'description' => 'required|string', 'tanggal_pengerjaan' => 'nullable|date', 'tanggal_selesai' => 'nullable|date', 'status' => 'nullable|string', @@ -76,13 +77,14 @@ public function update(Request $request, Jobdesk $jobdesk) [ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', - 'description' => 'nullable', + 'description' => 'required|string', 'tanggal_pengerjaan' => 'nullable', 'tanggal_selesai' => 'nullable', 'status' => 'required', ], [ 'order_id.required' => 'Pilih order yang akan dikerjakan.', + 'description.required' => 'Deskripsi harus diisi.', 'user_id.required' => 'Pilih karyawan yang akan mengerjakan jobdesk.', 'status.required' => 'Status harus diisi.', ] From bd6944a79013ab327e616d6904b24cd77cb0d5e2 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 14:21:23 +0700 Subject: [PATCH 096/184] fix meta crud --- app/Http/Controllers/MetaController.php | 28 +++++++++++++++++++------ routes/api.php | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/MetaController.php b/app/Http/Controllers/MetaController.php index 4e80863..ec4b8ef 100644 --- a/app/Http/Controllers/MetaController.php +++ b/app/Http/Controllers/MetaController.php @@ -15,10 +15,11 @@ public function index(Request $request) $paginate = $request->query('paginate'); if ($paginate === 'false') { - $meta = Meta::all(); + $meta = Meta::orderByDesc('id')->get(); } else { - $meta = Meta::paginate(25); + $meta = Meta::orderByDesc('id')->paginate(25); } + return response()->json($meta); } @@ -27,7 +28,14 @@ public function index(Request $request) */ public function store(Request $request) { - // + $request->validate([ + 'meta_key' => 'string|max:255|nullable', + 'meta_value' => 'string|nullable', + ]); + + $meta = Meta::create($request->all()); + + return response()->json($meta, 201); } /** @@ -35,7 +43,7 @@ public function store(Request $request) */ public function show(Meta $meta) { - // + return response()->json($meta); } /** @@ -43,7 +51,14 @@ public function show(Meta $meta) */ public function update(Request $request, Meta $meta) { - // + $request->validate([ + 'meta_key' => 'string|max:255|nullable', + 'meta_value' => 'string|nullable', + ]); + + $meta->update($request->all()); + + return response()->json($meta); } /** @@ -51,6 +66,7 @@ public function update(Request $request, Meta $meta) */ public function destroy(Meta $meta) { - // + $meta->delete(); + return response()->json(null, 204); } } diff --git a/routes/api.php b/routes/api.php index d2a85be..d4caf07 100644 --- a/routes/api.php +++ b/routes/api.php @@ -33,6 +33,6 @@ 'customers' => CustomerController::class, 'settings' => SettingController::class, 'products' => ProductController::class, - 'meta' => MetaController::class + 'metas' => MetaController::class ]); }); From 6fa3ea55f1d1a56f212c49f6a12b5dd929c40c67 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 14:40:03 +0700 Subject: [PATCH 097/184] fix product controller --- app/Http/Controllers/ProductController.php | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 85323cc..8224a5f 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -55,7 +55,7 @@ public function index(Request $request) }); } - return response()->json($products); + return response()->json($products, 200); } /** @@ -77,8 +77,16 @@ public function store(Request $request) $product->metaProducts()->create(['meta_id' => $metaId]); } } - - return response()->json($product, 201); + $response = [ + 'id' => $product->id, + 'name' => $product->name, + 'price' => $product->price, + 'description' => $product->description, + 'category' => $product->category, + 'meta_products' => $product->metaProducts->pluck('meta')->pluck('id'), + 'order_count' => $product->orders->count(), + ]; + return response()->json($response, 201); } /** @@ -114,7 +122,17 @@ public function update(Request $request, $id) } } $product->load('metaProducts.meta', 'orders'); - return response()->json($product); + + $response = [ + 'id' => $product->id, + 'name' => $product->name, + 'price' => $product->price, + 'description' => $product->description, + 'category' => $product->category, + 'meta_products' => $product->metaProducts->pluck('meta')->pluck('id'), + 'order_count' => $product->orders->count(), + ]; + return response()->json($response, 200); } /** From 21cfb273768301fc7e2b09a013d9294966911e8c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 15:32:00 +0700 Subject: [PATCH 098/184] change karyawan controller --- app/Http/Controllers/KaryawanController.php | 85 ++++++++++++++++----- app/Models/User.php | 5 ++ 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 3293bc8..9a498af 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -19,23 +19,53 @@ public function index(Request $request) $paginate = $request->query('paginate'); $name = $request->query('name'); - // Query dasar semua user - $query = User::query(); + // Query dasar semua user dengan relasi jobdesk + $query = User::with('jobdesk'); // Filter berdasarkan name jika ada if ($name && strlen($name) > 2) { $query->where('name', 'like', '%' . $name . '%'); } - // shorting descending + + // Sorting descending berdasarkan created_at $query->orderBy('created_at', 'desc'); // Check if pagination should be disabled if ($paginate === 'false') { // Get all records without pagination - $users = $query->get(); + $users = $query->get()->map(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'email' => $data->email, + 'is_admin' => strval($data->is_admin), + 'avatar' => $data->avatar, + 'phone' => $data->phone, + 'address' => $data->address, + 'position' => $data->position, + 'total_jobdesk' => $data->jobdesk->count(), + 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), + ]; + }); } else { // Paginate results $users = $query->paginate(25); + $users->getCollection()->transform(function ($data) { + return [ + 'id' => $data->id, + 'name' => $data->name, + 'email' => $data->email, + 'is_admin' => strval($data->is_admin), + 'avatar' => $data->avatar, + 'phone' => $data->phone, + 'address' => $data->address, + 'position' => $data->position, + 'total_jobdesk' => $data->jobdesk->count(), + 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), + ]; + }); } return response()->json($users); @@ -95,13 +125,22 @@ public function update(Request $request, $id) } // Update user dengan data yang tervalidasi - $user->update($validated); - - return response()->json([ - 'user' => $user, - 'message' => $message, - 'success' => true - ], 200); + $data = $user->update($validated); + $response = [ + 'id' => $data->id, + 'name' => $data->name, + 'email' => $data->email, + 'is_admin' => strval($data->is_admin), + 'avatar' => $data->avatar, + 'phone' => $data->phone, + 'address' => $data->address, + 'position' => $data->position, + 'total_jobdesk' => $data->jobdesk->count(), + 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), + ]; + + return response()->json($response, 200); } public function store(Request $request) @@ -124,13 +163,23 @@ public function store(Request $request) } $validated['password'] = bcrypt($validated['password']); - $user = User::create($validated); - - return response()->json([ - 'user' => $user, - 'message' => 'Data tersimpan', - 'success' => true - ], 200); + $data = User::create($validated); + + $response = [ + 'id' => $data->id, + 'name' => $data->name, + 'email' => $data->email, + 'is_admin' => strval($data->is_admin), + 'avatar' => $data->avatar, + 'phone' => $data->phone, + 'address' => $data->address, + 'position' => $data->position, + 'total_jobdesk' => $data->jobdesk->count(), + 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), + ]; + + return response()->json($response, 200); } public function destroy($id) diff --git a/app/Models/User.php b/app/Models/User.php index e7133a5..783cbcd 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -51,4 +51,9 @@ protected function casts(): array 'password' => 'hashed', ]; } + + public function jobdesk() + { + return $this->hasMany(Jobdesk::class); + } } From aec4fdfddd68d3423ddf5d7cb547456454d545bc Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 21:07:39 +0700 Subject: [PATCH 099/184] fix server compatible --- app/Http/Controllers/JobdeskController.php | 2 +- app/Http/Controllers/ProductController.php | 11 +++++++---- database/factories/CustomerFactory.php | 1 - .../2024_12_17_145546_create_notifications_table.php | 6 +++++- .../2025_01_08_224038_create_products_table.php | 2 +- database/seeders/UserSeeder.php | 4 ++-- 6 files changed, 16 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 3bc3230..4834d3f 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -23,7 +23,7 @@ public function index(Request $request) } // Filter by status if provided - if ($status && $status !== 'Masuk') { + if ($status) { $query->where('status', $status); } diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 8224a5f..e95e1bf 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -63,14 +63,15 @@ public function index(Request $request) */ public function store(Request $request) { - $request->validate([ + $validatedData = $request->validate([ 'name' => 'string|max:255|nullable', + 'category' => 'string', 'price' => 'numeric|nullable', 'description' => 'string|nullable', 'meta_products' => 'array|nullable', ]); - $product = Product::create($request->only('name', 'price', 'description')); + $product = Product::create($validatedData); if ($request->has('meta_products')) { foreach ($request->input('meta_products') as $metaId) { @@ -103,16 +104,18 @@ public function show($id) */ public function update(Request $request, $id) { - $request->validate([ + $validatedData = $request->validate([ 'name' => 'string|max:255|nullable', + 'category' => 'string', 'price' => 'numeric|nullable', 'description' => 'string|nullable', + 'meta_products' => 'array|nullable', 'meta_id' => 'array|nullable', ]); $product = Product::with('metaProducts.meta', 'orders')->findOrFail($id); - $product->update($request->only('name', 'price', 'description')); + $product->update($validatedData); // Update meta_id if ($request->has('meta_products')) { diff --git a/database/factories/CustomerFactory.php b/database/factories/CustomerFactory.php index 70658e2..0b09f6e 100644 --- a/database/factories/CustomerFactory.php +++ b/database/factories/CustomerFactory.php @@ -20,7 +20,6 @@ public function definition(): array 'name' => fake()->name(), 'phone' => fake()->phoneNumber(), 'address' => fake()->address(), - ]; } } diff --git a/database/migrations/2024_12_17_145546_create_notifications_table.php b/database/migrations/2024_12_17_145546_create_notifications_table.php index d738032..9bbe08a 100644 --- a/database/migrations/2024_12_17_145546_create_notifications_table.php +++ b/database/migrations/2024_12_17_145546_create_notifications_table.php @@ -14,10 +14,14 @@ public function up(): void Schema::create('notifications', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('type'); - $table->morphs('notifiable'); + $table->string('notifiable_type', 191); // Ubah panjang kolom + $table->uuid('notifiable_id'); // Pastikan ini sesuai dengan tipe ID yang Anda gunakan $table->text('data'); $table->timestamp('read_at')->nullable(); $table->timestamps(); + + // Tambahkan indeks jika diperlukan + $table->index(['notifiable_type', 'notifiable_id'], 'notifications_notifiable_type_notifiable_id_index'); }); } diff --git a/database/migrations/2025_01_08_224038_create_products_table.php b/database/migrations/2025_01_08_224038_create_products_table.php index a1f6b06..1ee1a06 100644 --- a/database/migrations/2025_01_08_224038_create_products_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -15,7 +15,7 @@ public function up(): void $table->id(); $table->string('name'); $table->string('price'); - $table->string('category'); + $table->string('category')->nullable(); $table->text('description')->nullable(); $table->timestamps(); }); diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 020cc8b..d2ebede 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -41,7 +41,7 @@ public function run() 'password' => Hash::make('password'), ]); User::factory()->create([ - 'name' => 'Test ', + 'name' => 'Test Staff', 'email' => 'staff@larapi.test', 'is_admin' => false, 'avatar' => null, @@ -52,6 +52,6 @@ public function run() ]); // Membuat 30 pengguna - User::factory(25)->create(); + User::factory(6)->create(); } } From 4921ae4cc9f77491c7ecd65bffdfbdd2ef823fb8 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 28 Jan 2025 22:05:14 +0700 Subject: [PATCH 100/184] fix jobdesk controller --- app/Http/Controllers/JobdeskController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 4834d3f..369b6ae 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -39,7 +39,7 @@ public function index(Request $request) } // Paginate the results - $jobdesk = $query->paginate(25); + $jobdesk = $query->orderBy('id', 'desc')->paginate(25); return response()->json($jobdesk); } From 2f91492cd5036001de996139b12528e350480b7b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 29 Jan 2025 07:50:56 +0700 Subject: [PATCH 101/184] fix customer preview --- app/Http/Controllers/CustomerController.php | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index e32cf7d..0a14308 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -84,7 +84,15 @@ public function store(Request $request) ); $customer = Customer::create($validatedData); - return response()->json($customer); + $response = [ + 'id' => $customer->id, + 'name' => $customer->name, + 'phone' => $customer->phone, + 'address' => $customer->address, + 'order_count' => $customer->orders->count(), + 'orders' => $customer->orders + ]; + return response()->json($response); } /** @@ -110,7 +118,17 @@ public function update(Request $request, Customer $customer) ] ); $customer->update($validatedData); - return response()->json($customer); + $customer->load('orders'); + + $response = [ + 'id' => $customer->id, + 'name' => $customer->name, + 'phone' => $customer->phone, + 'address' => $customer->address, + 'order_count' => $customer->orders->count(), + 'orders' => $customer->orders + ]; + return response()->json($response); } /** From 94e654b584514d8cb7f2fa19b85a3659b5cb230a Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 29 Jan 2025 11:28:22 +0700 Subject: [PATCH 102/184] fix jobdesk model typo --- app/Http/Controllers/JobdeskController.php | 53 +++++++++------------- app/Models/JobDesk.php | 2 +- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 369b6ae..1e1297b 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers; -use App\Models\Jobdesk; +use App\Models\JobDesk; use Illuminate\Http\Request; class JobdeskController extends Controller @@ -15,7 +15,7 @@ public function index(Request $request) $userId = $request->query('user_id'); // Initialize the query - $query = Jobdesk::with('order', 'order.customer', 'user', 'order.product'); + $query = JobDesk::with('order', 'order.customer', 'user', 'order.product'); // Filter by order_id if provided if ($orderId) { @@ -62,7 +62,7 @@ public function store(Request $request) if (isset($validatedData['tanggal_selesai'])) { $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); } - $jobdesk = Jobdesk::create($validatedData); + $jobdesk = JobDesk::create($validatedData); // relation $jobdesk->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk, 201); @@ -70,47 +70,36 @@ public function store(Request $request) return response()->json(['message' => 'Server Error', 'error' => $e->getMessage()], 500); } } - public function update(Request $request, Jobdesk $jobdesk) + public function update(Request $request, $id) { - $jobdesk = Jobdesk::find($jobdesk->id); - $validatedData = $request->validate( - [ + try { + $jobdesk = JobDesk::find($id); + $validatedData = $request->validate([ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', 'description' => 'required|string', - 'tanggal_pengerjaan' => 'nullable', - 'tanggal_selesai' => 'nullable', - 'status' => 'required', - ], - [ - 'order_id.required' => 'Pilih order yang akan dikerjakan.', - 'description.required' => 'Deskripsi harus diisi.', - 'user_id.required' => 'Pilih karyawan yang akan mengerjakan jobdesk.', - 'status.required' => 'Status harus diisi.', - ] - ); - if (isset($validatedData['tanggal_pengerjaan'])) { - $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); - } - - if (isset($validatedData['tanggal_selesai'])) { - $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); + 'tanggal_pengerjaan' => 'nullable|date', + 'tanggal_selesai' => 'nullable|date', + 'status' => 'nullable|string', + ]); + $jobdesk->update($validatedData); + $jobdesk->load('order', 'order.customer', 'user', 'order.product'); + return response()->json($jobdesk); + } catch (\Exception $e) { + return response()->json(['message' => 'Server Error', 'error' => $e->getMessage()], 500); } - $jobdesk->update($validatedData); - $jobdesk->load('order', 'order.customer', 'user', 'order.product'); - return response()->json($jobdesk); } - public function show(Jobdesk $jobdesk) + public function show(JobDesk $jobdesk) { - $jobdesk = Jobdesk::find($jobdesk->id)->load('order', 'order.customer', 'user', 'order.product'); + $jobdesk = JobDesk::find($jobdesk->id)->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk); } - public function destroy(Jobdesk $jobdesk) + public function destroy(JobDesk $jobdesk) { - $jobdesk = Jobdesk::find($jobdesk->id); + $jobdesk = JobDesk::find($jobdesk->id); $jobdesk->delete(); - return response()->json(['message' => 'Jobdesk deleted successfully']); + return response()->json(['message' => 'JobDesk deleted successfully']); } } diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php index 3617dde..7af3452 100644 --- a/app/Models/JobDesk.php +++ b/app/Models/JobDesk.php @@ -12,8 +12,8 @@ class Jobdesk extends Model protected $fillable = [ 'order_id', - 'description', 'user_id', + 'description', 'tanggal_pengerjaan', 'tanggal_selesai', 'status', From 607ede5ff3b042d3c0e8a5203fa00dd42adc02d7 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 29 Jan 2025 13:46:33 +0700 Subject: [PATCH 103/184] Hide sensitif data on staff --- app/Http/Controllers/DashboardController.php | 17 +++++--- app/Http/Controllers/JobdeskController.php | 24 +++++++---- app/Http/Controllers/OrderController.php | 35 ++++++++------- database/seeders/ProductSeeder.php | 45 +++++--------------- 4 files changed, 55 insertions(+), 66 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index ca8dd1f..f47f2b6 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -6,14 +6,17 @@ use App\Models\Order; use App\Models\Jobdesk; use App\Models\User; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\DB; class DashboardController extends Controller { /** * Display a summary of dashboard data. */ - public function index() + public function index(Request $request) { + $user = $request->user(); $totalCustomers = Customer::count(); $totalOrders = Order::count(); $totalKaryawan = User::count(); @@ -25,18 +28,18 @@ public function index() $totalBelumbayar = $totalTagihan - $totalPendapatan; // Menghitung jobdesk berdasarkan status - $totalJobdesk = Jobdesk::select('status', \DB::raw('count(*) as count')) + $totalJobdesk = Jobdesk::select('status', DB::raw('count(*) as count')) ->groupBy('status') ->pluck('count', 'status'); // Menyiapkan data untuk response $data = [ 'total_customers' => $totalCustomers, - 'total_orders' => $totalOrders, - 'total_pendapatan' => $totalPendapatan, - 'pendapatan_bulan_ini' => $pendapatanBulanIni, - 'total_tagihan' => $totalTagihan, - 'total_tagihan_bulan_ini' => $totalTagihanBulanIni, + 'total_orders' => $user->position !== 'Staff' ? $totalOrders : 0, + 'total_pendapatan' => $user->position !== 'Staff' ? $totalPendapatan : 0, + 'pendapatan_bulan_ini' => $user->position !== 'Staff' ? $pendapatanBulanIni : 0, + 'total_tagihan' => $user->position !== 'Staff' ? $totalTagihan : 0, + 'total_tagihan_bulan_ini' => $user->position !== 'Staff' ? $totalTagihanBulanIni : 0, 'total_karyawan' => $totalKaryawan, 'total_jobdesks' => [ 'Masuk' => $totalJobdesk->get('Masuk', 0), diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 1e1297b..72f1e39 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -2,7 +2,8 @@ namespace App\Http\Controllers; -use App\Models\JobDesk; +use App\Models\Jobdesk; +use App\Models\User; use Illuminate\Http\Request; class JobdeskController extends Controller @@ -13,15 +14,20 @@ public function index(Request $request) $status = $request->query('status'); $name = $request->query('name'); $userId = $request->query('user_id'); + $user = $request->user(); // Initialize the query - $query = JobDesk::with('order', 'order.customer', 'user', 'order.product'); + $query = Jobdesk::with('order', 'order.customer', 'user', 'order.product'); // Filter by order_id if provided if ($orderId) { $query->where('order_id', $orderId); } + if (in_array($user->position, ['Staff'])) { + $query->where('user_id', $user->id); + } + // Filter by status if provided if ($status) { $query->where('status', $status); @@ -62,7 +68,7 @@ public function store(Request $request) if (isset($validatedData['tanggal_selesai'])) { $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); } - $jobdesk = JobDesk::create($validatedData); + $jobdesk = Jobdesk::create($validatedData); // relation $jobdesk->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk, 201); @@ -73,7 +79,7 @@ public function store(Request $request) public function update(Request $request, $id) { try { - $jobdesk = JobDesk::find($id); + $jobdesk = Jobdesk::find($id); $validatedData = $request->validate([ 'order_id' => 'required|exists:orders,id', 'user_id' => 'required|exists:users,id', @@ -90,16 +96,16 @@ public function update(Request $request, $id) } } - public function show(JobDesk $jobdesk) + public function show(Jobdesk $jobdesk) { - $jobdesk = JobDesk::find($jobdesk->id)->load('order', 'order.customer', 'user', 'order.product'); + $jobdesk = Jobdesk::find($jobdesk->id)->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk); } - public function destroy(JobDesk $jobdesk) + public function destroy(Jobdesk $jobdesk) { - $jobdesk = JobDesk::find($jobdesk->id); + $jobdesk = Jobdesk::find($jobdesk->id); $jobdesk->delete(); - return response()->json(['message' => 'JobDesk deleted successfully']); + return response()->json(['message' => 'Jobdesk deleted successfully']); } } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 787dadd..c3ccfb0 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -22,6 +22,7 @@ class OrderController extends Controller 'meta' => 'nullable', 'customer_id' => 'required|exists:customers,id', ]; + public function index(Request $request) { $customerId = $request->query('customer_id'); @@ -30,6 +31,7 @@ public function index(Request $request) $product = $request->query('product'); $status = $request->query('status'); $status = isset($status) ? $status : null; + $user = $request->user(); $query = Order::with('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); @@ -71,16 +73,16 @@ public function index(Request $request) // Check if pagination should be disabled if ($paginate === 'false') { // Get all records without pagination - $orders = $query->get()->map(function ($data) { + $orders = $query->get()->map(function ($data) use ($user) { return [ 'id' => $data->id, 'no_order' => $data->no_order, 'customer_id' => $data->customer->id, 'order_date' => $data->order_date, 'product_id' => $data->product->id, - 'price' => $data->price, + 'price' => $user->position !== 'Staff' ? $data->price : 0, 'payment_method' => $data->payment_method, - 'paid' => $data->paid, + 'paid' => $user->position !== 'Staff' ? $data->paid : 0, 'meta' => $data->meta, 'lampiran' => $data->lampiran, 'jobdesk_count' => $data->jobdesks()->count(), @@ -95,7 +97,7 @@ public function index(Request $request) 'product' => [ 'id' => $data->product->id, 'name' => $data->product->name, - 'price' => $data->product->price, + 'price' => $user->position !== 'Staff' ? $data->product->price : 0, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), @@ -105,16 +107,16 @@ public function index(Request $request) } else { // Paginate results $orders = $query->paginate(25); - $orders->getCollection()->transform(function ($data) { + $orders->getCollection()->transform(function ($data) use ($user) { return [ 'id' => $data->id, 'no_order' => $data->no_order, 'customer_id' => $data->customer->id, 'order_date' => $data->order_date, 'product_id' => $data->product->id, - 'price' => $data->price, + 'price' => $user->position !== 'Staff' ? $data->price : 0, 'payment_method' => $data->payment_method, - 'paid' => $data->paid, + 'paid' => $user->position !== 'Staff' ? $data->paid : 0, 'meta' => $data->meta, 'lampiran' => $data->lampiran, 'jobdesk_count' => $data->jobdesks()->count(), @@ -129,11 +131,12 @@ public function index(Request $request) 'product' => [ 'id' => $data->product->id, 'name' => $data->product->name, - 'price' => $data->product->price, + 'price' => $user->position !== 'Staff' ? $data->product->price : 0, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), - ] + ], + 'position' => $user->position, ]; }); } @@ -148,6 +151,7 @@ public function show(Order $order) public function update(Request $request, Order $order) { + $user = $request->user(); // Validasi dokumen jika ada if ($request->hasFile('lampiran')) { // unset all validated data @@ -191,9 +195,9 @@ public function update(Request $request, Order $order) 'customer_id' => $order->customer->id, 'order_date' => $order->order_date, 'product_id' => $order->product->id, - 'price' => $order->price, + 'price' => $user->position !== 'Staff' ? $order->price : 0, 'payment_method' => $order->payment_method, - 'paid' => $order->paid, + 'paid' => $user->position !== 'Staff' ? $order->paid : 0, 'meta' => $order->meta, 'lampiran' => $order->lampiran, 'jobdesk_count' => $order->jobdesks()->count(), @@ -208,7 +212,7 @@ public function update(Request $request, Order $order) 'product' => [ 'id' => $order->product->id, 'name' => $order->product->name, - 'price' => $order->product->price, + 'price' => $user->position !== 'Staff' ? $order->product->price : 0, 'category' => $order->product->category, 'description' => $order->product->description, 'meta_products' => $order->product->metaProducts->pluck('meta'), @@ -219,6 +223,7 @@ public function update(Request $request, Order $order) public function store(Request $request) { + $user = $request->user(); $validator = Validator::make($request->all(), [ 'order_date' => 'required', 'product_id' => 'required', @@ -247,9 +252,9 @@ public function store(Request $request) 'customer_id' => $order->customer->id, 'order_date' => $order->order_date, 'product_id' => $order->product->id, - 'price' => $order->price, + 'price' => $user->position !== 'Staff' ? $order->price : 0, 'payment_method' => $order->payment_method, - 'paid' => $order->paid, + 'paid' => $user->position !== 'Staff' ? $order->paid : 0, 'meta' => $order->meta, 'lampiran' => $order->lampiran, 'jobdesk_count' => $order->jobdesks()->count(), @@ -264,7 +269,7 @@ public function store(Request $request) 'product' => [ 'id' => $order->product->id, 'name' => $order->product->name, - 'price' => $order->product->price, + 'price' => $user->position !== 'Staff' ? $order->product->price : 0, 'category' => $order->product->category, 'description' => $order->product->description, 'meta_products' => $order->product->metaProducts->pluck('meta'), diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index dafac4e..7325c3c 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -17,7 +17,7 @@ public function run(): void $products = [ 'perjanjian_kredit' => [ 'title' => 'Perjanjian Kredit', - 'meta' => [1, 2, 3, 4, 5, 6], + 'meta' => [1, 2, 3, 5, 6], 'category' => 'perorangan' ], 'skmht' => [ @@ -47,7 +47,7 @@ public function run(): void ], 'turun_waris' => [ 'title' => 'Turun Waris', - 'meta' => [22, 23, 24, 25, 26, 27, 28, 29, 30], + 'meta' => [23, 24, 25, 26, 27, 28, 29, 30], 'category' => 'perorangan', ], 'pecah' => [ @@ -57,45 +57,44 @@ public function run(): void ], 'pendirian_pt' => [ 'title' => 'Pendirian PT', - 'meta' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 43, 21, 44, 45, 52], 'category' => 'perorangan', ], 'pendirian_cv' => [ 'title' => 'Pendirian CV', - 'meta' => [1, 2, 3, 46, 47, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 46, 47, 21, 45, 52], 'category' => 'perorangan', ], 'pendirian_yayasan' => [ 'title' => 'Pendirian Yayasan', - 'meta' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'meta' => [1, 2, 3, 48, 49, 50, 51, 21, 52], 'category' => 'perorangan', ], 'pendirian_pt_perseorangan' => [ 'title' => 'Pendirian PT Perseorangan', - 'meta' => [1, 2, 3, 42, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 21, 45, 52], 'category' => 'perorangan', ], 'perubahan_pt' => [ 'title' => 'Perubahan PT', - 'meta' => [1, 2, 3, 42, 43, 21, 44, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 43, 21, 44, 45, 52], 'category' => 'perorangan', ], 'perubahan_cv' => [ 'title' => 'Perubahan CV', - 'meta' => [1, 2, 3, 46, 47, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 46, 47, 21, 45, 52], 'category' => 'perorangan', ], 'perubahan_yayasan' => [ 'title' => 'Perubahan Yayasan', - 'meta' => [1, 2, 3, 48, 49, 50, 51, 6, 21, 41, 52], + 'meta' => [1, 2, 3, 48, 49, 50, 51, 21, 52], 'category' => 'perorangan', ], 'perubahan_pt_perseorangan' => [ 'title' => 'Perubahan PT Perseorangan', - 'meta' => [1, 2, 3, 42, 21, 45, 41, 52], + 'meta' => [1, 2, 3, 42, 21, 45, 52], 'category' => 'perorangan', ], - // BPR BBA, BPR Pala Pusat, BPR Pala Cabang, BPR Danamas Prime, BPR Arum Mandiri, BPRS Madina Mandiri, BMT Sejahtera Ummat' 'bpr_bba' => [ 'title' => 'BPR BBA', 'meta' => [], @@ -145,18 +144,10 @@ public function run(): void 'title' => 'Tanggal Akta', 'type' => 'date' ], - 4 => [ - 'title' => 'Yang Mengerjakan', - 'type' => 'text' - ], 5 => [ 'title' => 'Jumlah Pinjaman', 'type' => 'number' ], - 6 => [ - 'title' => 'Lain-lain', - 'type' => 'text' - ], 7 => [ 'title' => 'Tanggal Habis SKMHT', 'type' => 'date' @@ -217,10 +208,6 @@ public function run(): void 'title' => 'NPWP', 'type' => 'text' ], - 22 => [ - 'title' => 'Berkas Masuk', - 'type' => 'text' - ], 23 => [ 'title' => 'Pewaris', 'type' => 'text' @@ -285,18 +272,6 @@ public function run(): void 'title' => 'Keterangan Kuasa Menjual', 'type' => 'text' ], - 39 => [ - 'title' => 'Harga Real', - 'type' => 'number' - ], - 40 => [ - 'title' => 'Harga Kesepakatan', - 'type' => 'number' - ], - 41 => [ - 'title' => 'Biaya', - 'type' => 'number' - ], 42 => [ 'title' => 'Nama Direktur', 'type' => 'text' From 0c83bf52341fc95e54d0274fdd098baea8a6d4a1 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 30 Jan 2025 09:23:28 +0700 Subject: [PATCH 104/184] perbaikan order & tipe data --- app/Http/Controllers/DashboardController.php | 6 +++--- app/Http/Controllers/JobdeskController.php | 2 +- app/Http/Controllers/OrderController.php | 2 +- app/Http/Controllers/SettingController.php | 1 + database/seeders/ProductSeeder.php | 12 ++++++------ 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index f47f2b6..7bd0d87 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -42,9 +42,9 @@ public function index(Request $request) 'total_tagihan_bulan_ini' => $user->position !== 'Staff' ? $totalTagihanBulanIni : 0, 'total_karyawan' => $totalKaryawan, 'total_jobdesks' => [ - 'Masuk' => $totalJobdesk->get('Masuk', 0), - 'Progress' => $totalJobdesk->get('Progress', 0), - 'Selesai' => $totalJobdesk->get('Selesai', 0), + 'Masuk' => (int) $totalJobdesk->get('Masuk', 0), + 'Progress' => (int) $totalJobdesk->get('Progress', 0), + 'Selesai' => (int) $totalJobdesk->get('Selesai', 0), ], ]; diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 72f1e39..da13295 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -45,7 +45,7 @@ public function index(Request $request) } // Paginate the results - $jobdesk = $query->orderBy('id', 'desc')->paginate(25); + $jobdesk = $query->orderBy('id', 'asc')->paginate(25); return response()->json($jobdesk); } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index c3ccfb0..6bef39c 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -68,7 +68,7 @@ public function index(Request $request) }); } - $query->orderBy('created_at', 'desc'); + $query->orderBy('created_at', 'asc'); // Check if pagination should be disabled if ($paginate === 'false') { diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index f489fdc..e914d6a 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -101,6 +101,7 @@ protected function validationRules() { return [ 'app_name' => 'nullable|string|max:255', + 'app_code' => 'nullable|string|max:255', 'app_description' => 'nullable|string|max:500', 'address' => 'nullable|string|max:255', 'banks' => 'nullable|string|max:2000', diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index 7325c3c..919e12f 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -146,7 +146,7 @@ public function run(): void ], 5 => [ 'title' => 'Jumlah Pinjaman', - 'type' => 'number' + 'type' => 'currency' ], 7 => [ 'title' => 'Tanggal Habis SKMHT', @@ -202,7 +202,7 @@ public function run(): void ], 20 => [ 'title' => 'Nilai Penjaminan', - 'type' => 'number' + 'type' => 'currency' ], 21 => [ 'title' => 'NPWP', @@ -226,7 +226,7 @@ public function run(): void ], 27 => [ 'title' => 'Nilai Pajak', - 'type' => 'number' + 'type' => 'currency' ], 28 => [ 'title' => 'Berkas Kembali', @@ -254,15 +254,15 @@ public function run(): void ], 34 => [ 'title' => 'Nilai Jual Beli', - 'type' => 'number' + 'type' => 'currency' ], 35 => [ 'title' => 'Nilai SSB', - 'type' => 'number' + 'type' => 'currency' ], 36 => [ 'title' => 'Nilai SSP', - 'type' => 'number' + 'type' => 'currency' ], 37 => [ 'title' => 'Keterangan PPJB', From fdd1d0007c93c22b1a4b00857cd250bc5d22f652 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 31 Jan 2025 20:32:52 +0700 Subject: [PATCH 105/184] fix dashboard ui --- app/Http/Controllers/DashboardController.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 7bd0d87..a482a2d 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -19,10 +19,12 @@ public function index(Request $request) $user = $request->user(); $totalCustomers = Customer::count(); $totalOrders = Order::count(); + $orderBulanIni = Order::whereMonth('order_date', now()->month)->count(); $totalKaryawan = User::count(); $totalPendapatan = intval(Order::sum('paid')); $pendapatanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('paid')); + $pendapatanBulanSebelumnya = intval(Order::whereMonth('order_date', now()->subMonth()->month)->sum('paid')); $totalTagihan = intval(Order::sum('price')); $totalTagihanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('price')); $totalBelumbayar = $totalTagihan - $totalPendapatan; @@ -35,9 +37,11 @@ public function index(Request $request) // Menyiapkan data untuk response $data = [ 'total_customers' => $totalCustomers, + 'order_bulan_ini' => $orderBulanIni, 'total_orders' => $user->position !== 'Staff' ? $totalOrders : 0, 'total_pendapatan' => $user->position !== 'Staff' ? $totalPendapatan : 0, 'pendapatan_bulan_ini' => $user->position !== 'Staff' ? $pendapatanBulanIni : 0, + 'pendapatan_bulan_sebelumnya' => $user->position !== 'Staff' ? $pendapatanBulanSebelumnya : 0, 'total_tagihan' => $user->position !== 'Staff' ? $totalTagihan : 0, 'total_tagihan_bulan_ini' => $user->position !== 'Staff' ? $totalTagihanBulanIni : 0, 'total_karyawan' => $totalKaryawan, From 331f8462c5711586280b614c10c284b9660a7b81 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 2 Feb 2025 13:05:08 +0700 Subject: [PATCH 106/184] update seeder & remove --- app/Http/Controllers/OrderController.php | 4 -- app/Http/Controllers/ProductController.php | 6 --- app/Models/Product.php | 1 - database/factories/ProductFactory.php | 1 - ...025_01_08_224038_create_products_table.php | 1 - database/seeders/DatabaseSeeder.php | 5 +- database/seeders/ProductSeeder.php | 48 +++++++++---------- 7 files changed, 27 insertions(+), 39 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 6bef39c..987c0e4 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -97,7 +97,6 @@ public function index(Request $request) 'product' => [ 'id' => $data->product->id, 'name' => $data->product->name, - 'price' => $user->position !== 'Staff' ? $data->product->price : 0, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), @@ -131,7 +130,6 @@ public function index(Request $request) 'product' => [ 'id' => $data->product->id, 'name' => $data->product->name, - 'price' => $user->position !== 'Staff' ? $data->product->price : 0, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), @@ -212,7 +210,6 @@ public function update(Request $request, Order $order) 'product' => [ 'id' => $order->product->id, 'name' => $order->product->name, - 'price' => $user->position !== 'Staff' ? $order->product->price : 0, 'category' => $order->product->category, 'description' => $order->product->description, 'meta_products' => $order->product->metaProducts->pluck('meta'), @@ -269,7 +266,6 @@ public function store(Request $request) 'product' => [ 'id' => $order->product->id, 'name' => $order->product->name, - 'price' => $user->position !== 'Staff' ? $order->product->price : 0, 'category' => $order->product->category, 'description' => $order->product->description, 'meta_products' => $order->product->metaProducts->pluck('meta'), diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index e95e1bf..50c057a 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -32,7 +32,6 @@ public function index(Request $request) return [ 'id' => $data->id, 'name' => $data->name, - 'price' => $data->price, 'description' => $data->description, 'category' => $data->category, 'meta' => $data->metaProducts->pluck('meta')->pluck('id'), @@ -46,7 +45,6 @@ public function index(Request $request) return [ 'id' => $data->id, 'name' => $data->name, - 'price' => $data->price, 'description' => $data->description, 'category' => $data->category, 'meta_products' => $data->metaProducts->pluck('meta')->pluck('id'), @@ -66,7 +64,6 @@ public function store(Request $request) $validatedData = $request->validate([ 'name' => 'string|max:255|nullable', 'category' => 'string', - 'price' => 'numeric|nullable', 'description' => 'string|nullable', 'meta_products' => 'array|nullable', ]); @@ -81,7 +78,6 @@ public function store(Request $request) $response = [ 'id' => $product->id, 'name' => $product->name, - 'price' => $product->price, 'description' => $product->description, 'category' => $product->category, 'meta_products' => $product->metaProducts->pluck('meta')->pluck('id'), @@ -107,7 +103,6 @@ public function update(Request $request, $id) $validatedData = $request->validate([ 'name' => 'string|max:255|nullable', 'category' => 'string', - 'price' => 'numeric|nullable', 'description' => 'string|nullable', 'meta_products' => 'array|nullable', 'meta_id' => 'array|nullable', @@ -129,7 +124,6 @@ public function update(Request $request, $id) $response = [ 'id' => $product->id, 'name' => $product->name, - 'price' => $product->price, 'description' => $product->description, 'category' => $product->category, 'meta_products' => $product->metaProducts->pluck('meta')->pluck('id'), diff --git a/app/Models/Product.php b/app/Models/Product.php index 9f0c0ea..070b6ed 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -11,7 +11,6 @@ class Product extends Model protected $fillable = [ 'name', - 'price', 'description', 'category', ]; diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php index 8fed164..22d35ad 100644 --- a/database/factories/ProductFactory.php +++ b/database/factories/ProductFactory.php @@ -13,7 +13,6 @@ public function definition() { return [ 'name' => $this->faker->word, - 'price' => $this->faker->randomFloat(0, 500000, 5000000), 'category' => $this->faker->randomElement(['bank', 'perorangan']), 'description' => $this->faker->paragraph, 'created_at' => now(), diff --git a/database/migrations/2025_01_08_224038_create_products_table.php b/database/migrations/2025_01_08_224038_create_products_table.php index 1ee1a06..c0db34f 100644 --- a/database/migrations/2025_01_08_224038_create_products_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -14,7 +14,6 @@ public function up(): void Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); - $table->string('price'); $table->string('category')->nullable(); $table->text('description')->nullable(); $table->timestamps(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 6a28526..0916f4d 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -17,7 +17,10 @@ public function run(): void { // Seed settings first $this->seedSettings(); - + $this->call([ + UserSeeder::class, + ProductSeeder::class, + ]); // Seed customers and orders $customers = Customer::factory(28)->create(); diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index 919e12f..1d9cfb7 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -17,7 +17,7 @@ public function run(): void $products = [ 'perjanjian_kredit' => [ 'title' => 'Perjanjian Kredit', - 'meta' => [1, 2, 3, 5, 6], + 'meta' => [1, 2, 3, 5], 'category' => 'perorangan' ], 'skmht' => [ @@ -95,41 +95,31 @@ public function run(): void 'meta' => [1, 2, 3, 42, 21, 45, 52], 'category' => 'perorangan', ], - 'bpr_bba' => [ - 'title' => 'BPR BBA', + 'bank_a' => [ + 'title' => 'Bank A', 'meta' => [], 'category' => 'bank', ], - 'bpr_pala_pusat' => [ - 'title' => 'BPR Pala Pusat', + 'bank_b' => [ + 'title' => 'Bank B', 'meta' => [], 'category' => 'bank', ], - 'bpr_pala_cabang' => [ - 'title' => 'BPR Pala Cabang', + 'bank_c' => [ + 'title' => 'Bank C', 'meta' => [], 'category' => 'bank', ], - 'bpr_danamas_prime' => [ - 'title' => 'BPR Danamas Prime', + 'bank_d' => [ + 'title' => 'Bank D', 'meta' => [], 'category' => 'bank', ], - 'bpr_arum_mandiri' => [ - 'title' => 'BPR Arum Mandiri', + 'bank_e' => [ + 'title' => 'Bank E', 'meta' => [], 'category' => 'bank', ], - 'bprs_madina_mandiri' => [ - 'title' => 'BPRS Madina Mandiri', - 'meta' => [], - 'category' => 'bank', - ], - 'bmt_sejahtera_ummat' => [ - 'title' => 'BMT Sejahtera Ummat', - 'meta' => [], - 'category' => 'bank', - ] ]; $metas = [ 1 => [ @@ -330,17 +320,25 @@ public function run(): void // Insert meta ke tabel 'products' dan 'meta_product' foreach ($products as $slug => $product) { + // Insert data ke tabel 'products' $productId = Product::factory()->create([ 'name' => $product['title'], 'description' => '-', 'category' => $product['category'] ]); + // Insert data ke tabel 'meta_product' foreach ($product['meta'] as $metaId) { - MetaProduct::factory()->create([ - 'meta_id' => $metaId, - 'product_id' => $productId - ]); + // Pastikan meta_id ada di tabel 'metas' + if (Meta::where('id', $metaId)->exists()) { + MetaProduct::factory()->create([ + 'meta_id' => $metaId, + 'product_id' => $productId + ]); + } else { + // Jika meta_id tidak ditemukan, tampilkan pesan error atau log + echo "Meta ID $metaId tidak ditemukan di tabel 'metas'. Produk: {$product['title']}\n"; + } } } } From 39c7689485601bf34284d821fce4aebef2bb6543 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 3 Feb 2025 07:59:35 +0700 Subject: [PATCH 107/184] remove product price --- app/Http/Controllers/OrderController.php | 4 ---- app/Http/Controllers/ProductController.php | 6 ------ app/Models/Product.php | 1 - database/factories/ProductFactory.php | 1 - .../migrations/2025_01_08_224038_create_products_table.php | 1 - 5 files changed, 13 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 6bef39c..987c0e4 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -97,7 +97,6 @@ public function index(Request $request) 'product' => [ 'id' => $data->product->id, 'name' => $data->product->name, - 'price' => $user->position !== 'Staff' ? $data->product->price : 0, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), @@ -131,7 +130,6 @@ public function index(Request $request) 'product' => [ 'id' => $data->product->id, 'name' => $data->product->name, - 'price' => $user->position !== 'Staff' ? $data->product->price : 0, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), @@ -212,7 +210,6 @@ public function update(Request $request, Order $order) 'product' => [ 'id' => $order->product->id, 'name' => $order->product->name, - 'price' => $user->position !== 'Staff' ? $order->product->price : 0, 'category' => $order->product->category, 'description' => $order->product->description, 'meta_products' => $order->product->metaProducts->pluck('meta'), @@ -269,7 +266,6 @@ public function store(Request $request) 'product' => [ 'id' => $order->product->id, 'name' => $order->product->name, - 'price' => $user->position !== 'Staff' ? $order->product->price : 0, 'category' => $order->product->category, 'description' => $order->product->description, 'meta_products' => $order->product->metaProducts->pluck('meta'), diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index e95e1bf..50c057a 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -32,7 +32,6 @@ public function index(Request $request) return [ 'id' => $data->id, 'name' => $data->name, - 'price' => $data->price, 'description' => $data->description, 'category' => $data->category, 'meta' => $data->metaProducts->pluck('meta')->pluck('id'), @@ -46,7 +45,6 @@ public function index(Request $request) return [ 'id' => $data->id, 'name' => $data->name, - 'price' => $data->price, 'description' => $data->description, 'category' => $data->category, 'meta_products' => $data->metaProducts->pluck('meta')->pluck('id'), @@ -66,7 +64,6 @@ public function store(Request $request) $validatedData = $request->validate([ 'name' => 'string|max:255|nullable', 'category' => 'string', - 'price' => 'numeric|nullable', 'description' => 'string|nullable', 'meta_products' => 'array|nullable', ]); @@ -81,7 +78,6 @@ public function store(Request $request) $response = [ 'id' => $product->id, 'name' => $product->name, - 'price' => $product->price, 'description' => $product->description, 'category' => $product->category, 'meta_products' => $product->metaProducts->pluck('meta')->pluck('id'), @@ -107,7 +103,6 @@ public function update(Request $request, $id) $validatedData = $request->validate([ 'name' => 'string|max:255|nullable', 'category' => 'string', - 'price' => 'numeric|nullable', 'description' => 'string|nullable', 'meta_products' => 'array|nullable', 'meta_id' => 'array|nullable', @@ -129,7 +124,6 @@ public function update(Request $request, $id) $response = [ 'id' => $product->id, 'name' => $product->name, - 'price' => $product->price, 'description' => $product->description, 'category' => $product->category, 'meta_products' => $product->metaProducts->pluck('meta')->pluck('id'), diff --git a/app/Models/Product.php b/app/Models/Product.php index 9f0c0ea..070b6ed 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -11,7 +11,6 @@ class Product extends Model protected $fillable = [ 'name', - 'price', 'description', 'category', ]; diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php index 8fed164..22d35ad 100644 --- a/database/factories/ProductFactory.php +++ b/database/factories/ProductFactory.php @@ -13,7 +13,6 @@ public function definition() { return [ 'name' => $this->faker->word, - 'price' => $this->faker->randomFloat(0, 500000, 5000000), 'category' => $this->faker->randomElement(['bank', 'perorangan']), 'description' => $this->faker->paragraph, 'created_at' => now(), diff --git a/database/migrations/2025_01_08_224038_create_products_table.php b/database/migrations/2025_01_08_224038_create_products_table.php index 1ee1a06..c0db34f 100644 --- a/database/migrations/2025_01_08_224038_create_products_table.php +++ b/database/migrations/2025_01_08_224038_create_products_table.php @@ -14,7 +14,6 @@ public function up(): void Schema::create('products', function (Blueprint $table) { $table->id(); $table->string('name'); - $table->string('price'); $table->string('category')->nullable(); $table->text('description')->nullable(); $table->timestamps(); From b3047d2fd6450ec89803a18ff2efe1c29d5e2167 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 3 Feb 2025 08:03:41 +0700 Subject: [PATCH 108/184] fix new seeder stucture --- database/seeders/DatabaseSeeder.php | 5 +++++ database/seeders/ProductSeeder.php | 16 ++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 6a28526..9dca074 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -15,6 +15,11 @@ class DatabaseSeeder extends Seeder */ public function run(): void { + + $this->call([ + UserSeeder::class, + ProductSeeder::class, + ]); // Seed settings first $this->seedSettings(); diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index 919e12f..2c8d714 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -330,17 +330,25 @@ public function run(): void // Insert meta ke tabel 'products' dan 'meta_product' foreach ($products as $slug => $product) { + // Insert data ke tabel 'products' $productId = Product::factory()->create([ 'name' => $product['title'], 'description' => '-', 'category' => $product['category'] ]); + // Insert data ke tabel 'meta_product' foreach ($product['meta'] as $metaId) { - MetaProduct::factory()->create([ - 'meta_id' => $metaId, - 'product_id' => $productId - ]); + // Pastikan meta_id ada di tabel 'metas' + if (Meta::where('id', $metaId)->exists()) { + MetaProduct::factory()->create([ + 'meta_id' => $metaId, + 'product_id' => $productId + ]); + } else { + // Jika meta_id tidak ditemukan, tampilkan pesan error atau log + echo "Meta ID $metaId tidak ditemukan di tabel 'metas'. Produk: {$product['title']}\n"; + } } } } From 16c069482cf21ee7f6cc19802bbf0b1f00b71511 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 3 Feb 2025 15:37:01 +0700 Subject: [PATCH 109/184] fix controller customer --- app/Http/Controllers/CustomerController.php | 28 ++++++++++++--------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 0a14308..0913934 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -85,12 +85,14 @@ public function store(Request $request) $customer = Customer::create($validatedData); $response = [ - 'id' => $customer->id, - 'name' => $customer->name, - 'phone' => $customer->phone, - 'address' => $customer->address, - 'order_count' => $customer->orders->count(), - 'orders' => $customer->orders + 'data' => [ + 'id' => $customer->id, + 'name' => $customer->name, + 'phone' => $customer->phone, + 'address' => $customer->address, + 'order_count' => $customer->orders->count(), + 'orders' => $customer->orders + ] ]; return response()->json($response); } @@ -121,12 +123,14 @@ public function update(Request $request, Customer $customer) $customer->load('orders'); $response = [ - 'id' => $customer->id, - 'name' => $customer->name, - 'phone' => $customer->phone, - 'address' => $customer->address, - 'order_count' => $customer->orders->count(), - 'orders' => $customer->orders + 'data' => [ + 'id' => $customer->id, + 'name' => $customer->name, + 'phone' => $customer->phone, + 'address' => $customer->address, + 'order_count' => $customer->orders->count(), + 'orders' => $customer->orders + ] ]; return response()->json($response); } From 504e791c1158181c67dd05a514745f0739422c8f Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 3 Feb 2025 22:04:46 +0700 Subject: [PATCH 110/184] ix database seeder --- database/seeders/DatabaseSeeder.php | 4 ---- database/seeders/ProductSeeder.php | 6 +++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d16f1b9..acb24b9 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -22,10 +22,6 @@ public function run(): void ]); // Seed settings first $this->seedSettings(); - $this->call([ - UserSeeder::class, - ProductSeeder::class, - ]); // Seed customers and orders $customers = Customer::factory(28)->create(); diff --git a/database/seeders/ProductSeeder.php b/database/seeders/ProductSeeder.php index 1d9cfb7..23cbdd5 100644 --- a/database/seeders/ProductSeeder.php +++ b/database/seeders/ProductSeeder.php @@ -37,7 +37,7 @@ public function run(): void ], 'jual_beli' => [ 'title' => 'Jual Beli', - 'meta' => [2, 3, 31, 32, 33, 26, 34, 35, 36, 37, 38], + 'meta' => [2, 3, 4, 31, 32, 33, 26, 34, 35, 36, 37, 38], 'category' => 'perorangan', ], 'hibah' => [ @@ -134,6 +134,10 @@ public function run(): void 'title' => 'Tanggal Akta', 'type' => 'date' ], + 4 => [ + 'title' => 'Harga Real', + 'type' => 'currency' + ], 5 => [ 'title' => 'Jumlah Pinjaman', 'type' => 'currency' From 2648fc99d3eb52934eb1b6ff3cc063914eac3b7d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 7 Feb 2025 11:38:10 +0700 Subject: [PATCH 111/184] fix delete customer & user policy --- app/Http/Controllers/CustomerController.php | 13 +++++++++++ app/Http/Controllers/OrderController.php | 18 +++++++++------- app/Policies/CustomerPolicy.php | 24 +++++++++++++++------ app/Policies/UserPolicy.php | 1 + 4 files changed, 41 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 0913934..c3c09c3 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -140,7 +140,20 @@ public function update(Request $request, Customer $customer) */ public function destroy(Customer $customer) { + // Retrieve all orders for the customer + $orders = $customer->orders; + + // Loop through each order and delete related jobdesks + foreach ($orders as $order) { + $order->jobdesks()->delete(); // Ensure jobdesks relationship exists on Order + } + + // Now delete the orders themselves + $customer->orders()->delete(); + + // Finally, delete the customer $customer->delete(); + return response()->json($customer); } } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 987c0e4..606069b 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -77,9 +77,9 @@ public function index(Request $request) return [ 'id' => $data->id, 'no_order' => $data->no_order, - 'customer_id' => $data->customer->id, + 'customer_id' => $data->customer->id ?? null, 'order_date' => $data->order_date, - 'product_id' => $data->product->id, + 'product_id' => $data->product->id ?? null, 'price' => $user->position !== 'Staff' ? $data->price : 0, 'payment_method' => $data->payment_method, 'paid' => $user->position !== 'Staff' ? $data->paid : 0, @@ -110,9 +110,9 @@ public function index(Request $request) return [ 'id' => $data->id, 'no_order' => $data->no_order, - 'customer_id' => $data->customer->id, + 'customer_id' => $data->customer->id ?? null, 'order_date' => $data->order_date, - 'product_id' => $data->product->id, + 'product_id' => $data->product->id ?? null, 'price' => $user->position !== 'Staff' ? $data->price : 0, 'payment_method' => $data->payment_method, 'paid' => $user->position !== 'Staff' ? $data->paid : 0, @@ -120,20 +120,20 @@ public function index(Request $request) 'lampiran' => $data->lampiran, 'jobdesk_count' => $data->jobdesks()->count(), 'created_at' => $data->created_at, - 'customer' => [ + 'customer' => $data->customer ? [ 'id' => $data->customer->id, 'name' => $data->customer->name, 'phone' => $data->customer->phone, 'address' => $data->customer->address, - ], + ] : null, 'jobdesks' => $data->jobdesks, - 'product' => [ + 'product' => $data->product ? [ 'id' => $data->product->id, 'name' => $data->product->name, 'category' => $data->product->category, 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), - ], + ] : null, 'position' => $user->position, ]; }); @@ -276,6 +276,8 @@ public function store(Request $request) public function destroy(Order $order) { + $order = Order::find($order->id); + $order->jobdesks()->delete(); $order->delete(); return response()->json($order); } diff --git a/app/Policies/CustomerPolicy.php b/app/Policies/CustomerPolicy.php index b4f2724..8db5942 100644 --- a/app/Policies/CustomerPolicy.php +++ b/app/Policies/CustomerPolicy.php @@ -13,7 +13,8 @@ class CustomerPolicy */ public function viewAny(User $user): bool { - // + // Allow admin users to view any customer + return $user->is_admin === 1; } /** @@ -21,7 +22,9 @@ public function viewAny(User $user): bool */ public function view(User $user, Customer $customer): bool { - // + // Allow admin users to view any customer + // Allow regular users to view their own customers + return $user->is_admin === 1 || $user->id === $customer->user_id; } /** @@ -29,7 +32,8 @@ public function view(User $user, Customer $customer): bool */ public function create(User $user): bool { - // + // Allow admin users to create customers + return $user->is_admin === 1; } /** @@ -37,7 +41,9 @@ public function create(User $user): bool */ public function update(User $user, Customer $customer): bool { - // + // Allow admin users to update any customer + // Allow regular users to update their own customers + return $user->is_admin === 1 || $user->id === $customer->user_id; } /** @@ -45,7 +51,9 @@ public function update(User $user, Customer $customer): bool */ public function delete(User $user, Customer $customer): bool { - // + // Allow admin users to delete any customer + // You may also want to allow the customer’s owner to delete their own record + return $user->is_admin === 1 || $user->id === $customer->user_id; } /** @@ -53,7 +61,8 @@ public function delete(User $user, Customer $customer): bool */ public function restore(User $user, Customer $customer): bool { - // + // Typically allow only admins to restore customers + return $user->is_admin === 1; } /** @@ -61,6 +70,7 @@ public function restore(User $user, Customer $customer): bool */ public function forceDelete(User $user, Customer $customer): bool { - // + // Typically allow only admins to permanently delete customers + return $user->is_admin === 1; } } diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index bbd9b6e..81a8b1e 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -26,6 +26,7 @@ public function delete(User $authUser, User $user) // Memeriksa apakah pengguna yang sedang login adalah pengguna yang sama // atau jika pengguna tersebut adalah admin // dan jika user yang dihapus bukan admin + $authUser->is_admin = (int) $authUser->is_admin; return ($authUser->id === $user->id || $authUser->is_admin === 1) && $user->is_admin !== 1; } } From f6efecd09e486a45073f670ddb2a5cf9912c9868 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 7 Feb 2025 21:48:34 +0700 Subject: [PATCH 112/184] penanggung jawab hanyaa keluar staff --- app/Http/Controllers/KaryawanController.php | 28 +++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 9a498af..aaee47f 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -18,6 +18,7 @@ public function index(Request $request) { $paginate = $request->query('paginate'); $name = $request->query('name'); + $position = $request->query('position'); // Query dasar semua user dengan relasi jobdesk $query = User::with('jobdesk'); @@ -27,6 +28,11 @@ public function index(Request $request) $query->where('name', 'like', '%' . $name . '%'); } + // Filter berdasarkan position jika ada + if ($position) { + $query->where('position', $position); + } + // Sorting descending berdasarkan created_at $query->orderBy('created_at', 'desc'); @@ -94,10 +100,8 @@ public function update(Request $request, $id) 'avatar' => 'nullable', ]); - // Abaikan 'avatar' jika merupakan string, hanya lanjutkan jika file - if (is_string($request->avatar)) { - unset($validated['avatar']); - } elseif ($request->hasFile('avatar')) { + // Handle Avatar + if ($request->hasFile('avatar')) { $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); // Hapus avatar lama jika ada @@ -106,17 +110,17 @@ public function update(Request $request, $id) } } else { // Jika tidak ada file avatar, gunakan avatar yang ada - $validated['avatar'] = $user->avatar; + unset($validated['avatar']); } - // Hanya update password jika diisi - if (isset($validated['password']) && !empty($validated['password'])) { - $validated['password'] = bcrypt($validated['password']); + // Handle Password + if (!empty($validated['password'])) { + $validated['password'] = Hash::make($validated['password']); } else { unset($validated['password']); } - // Cek jika user bukan admin dan coba mengupdate position, maka abaikan perubahan position + // Cek jika user bukan admin dan coba mengupdate position if ($requested_user->is_admin !== 1 && isset($validated['position'])) { $validated['position'] = $user->position; $message = 'Data tersimpan, position tidak bisa diupdate'; @@ -125,7 +129,11 @@ public function update(Request $request, $id) } // Update user dengan data yang tervalidasi - $data = $user->update($validated); + $user->update($validated); + + // Retrieve the updated user data + $data = User::find($id); + $response = [ 'id' => $data->id, 'name' => $data->name, From 7705cf8c11ec5fce32dee0e66f5f70856035cd27 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 7 Feb 2025 22:28:52 +0700 Subject: [PATCH 113/184] fix tipedata is admin --- app/Http/Controllers/KaryawanController.php | 38 ++++-------- app/Policies/UserPolicy.php | 2 +- database/seeders/UserSeeder.php | 64 ++++++++++----------- 3 files changed, 44 insertions(+), 60 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index aaee47f..d48e0e9 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -103,13 +103,10 @@ public function update(Request $request, $id) // Handle Avatar if ($request->hasFile('avatar')) { $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); - - // Hapus avatar lama jika ada if ($user->avatar) { Storage::disk('public')->delete($user->avatar); } } else { - // Jika tidak ada file avatar, gunakan avatar yang ada unset($validated['avatar']); } @@ -120,35 +117,22 @@ public function update(Request $request, $id) unset($validated['password']); } - // Cek jika user bukan admin dan coba mengupdate position + // Check for position update if ($requested_user->is_admin !== 1 && isset($validated['position'])) { $validated['position'] = $user->position; - $message = 'Data tersimpan, position tidak bisa diupdate'; - } else { - $message = 'Data tersimpan'; } - // Update user dengan data yang tervalidasi - $user->update($validated); - - // Retrieve the updated user data - $data = User::find($id); - - $response = [ - 'id' => $data->id, - 'name' => $data->name, - 'email' => $data->email, - 'is_admin' => strval($data->is_admin), - 'avatar' => $data->avatar, - 'phone' => $data->phone, - 'address' => $data->address, - 'position' => $data->position, - 'total_jobdesk' => $data->jobdesk->count(), - 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), - 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), - ]; + // Update user + $updated = $user->update($validated); - return response()->json($response, 200); + // Check if the update was successful + if ($updated) { + // Retrieve the updated user data + $data = User::find($id); + return response()->json($data, 200); + } else { + return response()->json(['message' => 'Update failed'], 400); + } } public function store(Request $request) diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 81a8b1e..8cc6c7b 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -18,7 +18,7 @@ public function update(User $authUser, User $user) { // Memeriksa apakah pengguna yang sedang login adalah pengguna yang sama // atau jika pengguna tersebut adalah admin - return $authUser->id === $user->id || $authUser->is_admin === 1; + return $authUser->id === $user->id || (int) $authUser->is_admin === 1; } public function delete(User $authUser, User $user) diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index d2ebede..b1ea0dc 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -20,38 +20,38 @@ public function run() 'position' => 'Manager', 'password' => Hash::make('password'), ]); - User::factory()->create([ - 'name' => 'Test Manager', - 'email' => 'manager@larapi.test', - 'is_admin' => false, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Manager', - 'password' => Hash::make('password'), - ]); - User::factory()->create([ - 'name' => 'Test Keuangan', - 'email' => 'keuangan@larapi.test', - 'is_admin' => false, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Keuangan', - 'password' => Hash::make('password'), - ]); - User::factory()->create([ - 'name' => 'Test Staff', - 'email' => 'staff@larapi.test', - 'is_admin' => false, - 'avatar' => null, - 'phone' => '08123456789', - 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Staff', - 'password' => Hash::make('password'), - ]); + // User::factory()->create([ + // 'name' => 'Test Manager', + // 'email' => 'manager@larapi.test', + // 'is_admin' => false, + // 'avatar' => null, + // 'phone' => '08123456789', + // 'address' => 'Jl. Kebon Jeruk No. 1', + // 'position' => 'Manager', + // 'password' => Hash::make('password'), + // ]); + // User::factory()->create([ + // 'name' => 'Test Keuangan', + // 'email' => 'keuangan@larapi.test', + // 'is_admin' => false, + // 'avatar' => null, + // 'phone' => '08123456789', + // 'address' => 'Jl. Kebon Jeruk No. 1', + // 'position' => 'Keuangan', + // 'password' => Hash::make('password'), + // ]); + // User::factory()->create([ + // 'name' => 'Test Staff', + // 'email' => 'staff@larapi.test', + // 'is_admin' => false, + // 'avatar' => null, + // 'phone' => '08123456789', + // 'address' => 'Jl. Kebon Jeruk No. 1', + // 'position' => 'Staff', + // 'password' => Hash::make('password'), + // ]); - // Membuat 30 pengguna - User::factory(6)->create(); + // // Membuat 30 pengguna + // User::factory(6)->create(); } } From 5f5664cd0b2b029dcf58fad50759c636e8c6dbf9 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 7 Feb 2025 23:51:19 +0700 Subject: [PATCH 114/184] format tanggal ganti pakai carbon --- app/Http/Controllers/DashboardController.php | 2 +- app/Http/Controllers/JobdeskController.php | 14 ++++++++------ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index a482a2d..48e4f87 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -25,7 +25,7 @@ public function index(Request $request) $totalPendapatan = intval(Order::sum('paid')); $pendapatanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('paid')); $pendapatanBulanSebelumnya = intval(Order::whereMonth('order_date', now()->subMonth()->month)->sum('paid')); - $totalTagihan = intval(Order::sum('price')); + $totalTagihan = intval(Order::sum('price')) - $totalPendapatan; $totalTagihanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('price')); $totalBelumbayar = $totalTagihan - $totalPendapatan; diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index da13295..d864bb2 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -5,6 +5,7 @@ use App\Models\Jobdesk; use App\Models\User; use Illuminate\Http\Request; +use Carbon\Carbon; class JobdeskController extends Controller { @@ -62,12 +63,9 @@ public function store(Request $request) 'status' => 'nullable|string', ]); - if (isset($validatedData['tanggal_pengerjaan'])) { - $validatedData['tanggal_pengerjaan'] = date('Y-m-d', strtotime($validatedData['tanggal_pengerjaan'])); - } - if (isset($validatedData['tanggal_selesai'])) { - $validatedData['tanggal_selesai'] = date('Y-m-d', strtotime($validatedData['tanggal_selesai'])); - } + $validatedData['tanggal_pengerjaan'] = $validatedData['tanggal_pengerjaan'] ? Carbon::parse($validatedData['tanggal_pengerjaan'])->setTimezone('Asia/Jakarta')->startOfDay() : null; + $validatedData['tanggal_selesai'] = $validatedData['tanggal_selesai'] ? Carbon::parse($validatedData['tanggal_selesai'])->setTimezone('Asia/Jakarta')->endOfDay() : null; + $jobdesk = Jobdesk::create($validatedData); // relation $jobdesk->load('order', 'order.customer', 'user', 'order.product'); @@ -88,6 +86,10 @@ public function update(Request $request, $id) 'tanggal_selesai' => 'nullable|date', 'status' => 'nullable|string', ]); + + $validatedData['tanggal_pengerjaan'] = $validatedData['tanggal_pengerjaan'] ? Carbon::parse($validatedData['tanggal_pengerjaan'])->setTimezone('Asia/Jakarta')->startOfDay() : null; + $validatedData['tanggal_selesai'] = $validatedData['tanggal_selesai'] ? Carbon::parse($validatedData['tanggal_selesai'])->setTimezone('Asia/Jakarta')->endOfDay() : null; + $jobdesk->update($validatedData); $jobdesk->load('order', 'order.customer', 'user', 'order.product'); return response()->json($jobdesk); From 86909bbdad1495bc22eccddb057333f016cce762 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 8 Feb 2025 07:38:23 +0700 Subject: [PATCH 115/184] fix filter product --- app/Http/Controllers/OrderController.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 606069b..5278dcc 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -28,7 +28,7 @@ public function index(Request $request) $customerId = $request->query('customer_id'); $paginate = $request->query('paginate'); $name = $request->query('name'); - $product = $request->query('product'); + $productQuery = $request->query('product'); $status = $request->query('status'); $status = isset($status) ? $status : null; $user = $request->user(); @@ -39,10 +39,13 @@ public function index(Request $request) $query->where('customer_id', $customerId); } - if ($name && strlen($name) > 2 && !$customerId) { + if ($name || $productQuery) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); }); + $query->whereHas('product', function ($query) use ($productQuery) { + $query->where('name', 'like', '%' . $productQuery . '%'); + }); } else { if ($status) { $query->whereDoesntHave('jobdesks', function ($query) use ($status) { @@ -62,12 +65,6 @@ public function index(Request $request) } } - if ($product && strlen($product) > 2) { - $query->whereHas('product', function ($query) use ($product) { - $query->where('name', 'like', '%' . $product . '%'); - }); - } - $query->orderBy('created_at', 'asc'); // Check if pagination should be disabled From 65e220f48284f1d5eee05d458bbe5bb556c814a7 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 8 Feb 2025 08:37:42 +0700 Subject: [PATCH 116/184] fix upload document --- app/Http/Controllers/OrderController.php | 44 +++++++++++------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 5278dcc..329b5a0 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -147,18 +147,25 @@ public function show(Order $order) public function update(Request $request, Order $order) { $user = $request->user(); - // Validasi dokumen jika ada + + // Jika ada lampiran, hanya validasi lampiran if ($request->hasFile('lampiran')) { - // unset all validated data - $this->validate = []; - $this->validate = [ + $request->validate([ 'lampiran' => 'required|mimes:pdf', - ]; - } + ]); + + $filePath = $request->file('lampiran')->store('lampiran', 'public'); - // Validasi data yang diterima - $validatedData = $request->validate( - [ + // Hapus dokumen lama jika ada + if ($order->lampiran) { + Storage::disk('public')->delete($order->lampiran); + } + + // Update order dengan lampiran baru + $order->update(['lampiran' => $filePath]); + } else { + // Validasi data lain jika lampiran tidak ada + $validatedData = $request->validate([ 'order_date' => 'required', 'product_id' => 'required', 'price' => 'required', @@ -166,23 +173,13 @@ public function update(Request $request, Order $order) 'payment_method' => 'required', 'meta' => 'nullable', 'customer' => 'required', - ] - ); - - // Validasi dokumen jika ada - if ($request->hasFile('lampiran')) { - $this->validate['lampiran'] = 'required|mimes:pdf'; - $filePath = $request->file('lampiran')->store('lampiran', 'public'); - $validatedData['lampiran'] = $filePath; - } + ]); - // Cek dan hapus dokumen lama jika ada - if ($order->lampiran) { - Storage::disk('public')->delete($order->lampiran); + // Update order dengan data yang sudah divalidasi + $order->update($validatedData); } - // Update order dengan data yang sudah divalidasi - $order->update($validatedData); + // Load relasi dan respon $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); $response = [ 'id' => $order->id, @@ -212,6 +209,7 @@ public function update(Request $request, Order $order) 'meta_products' => $order->product->metaProducts->pluck('meta'), ] ]; + return response()->json($response); } From b6d6bcc8a442e24118f61da861892bcf62d0bb15 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 10 Feb 2025 11:30:53 +0700 Subject: [PATCH 117/184] fix seeder to trial notif --- database/factories/JobDeskFactory.php | 4 +- database/factories/OrderFactory.php | 9 +++- database/seeders/UserSeeder.php | 73 +++++++++++++++------------ 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php index 180c685..937d97e 100644 --- a/database/factories/JobDeskFactory.php +++ b/database/factories/JobDeskFactory.php @@ -19,11 +19,11 @@ class JobdeskFactory extends Factory public function definition(): array { $status = random_int(1, 100) <= 80 ? 'Selesai' : fake()->randomElement(['Masuk', 'Progress']); - + $staffs = User::where('position', 'Staff')->get(); return [ 'order_id' => fake()->numberBetween(1, 10), 'description' => fake()->sentence(), - 'user_id' => $status !== 'Masuk' ? fake()->numberBetween(1, 10) : null, + 'user_id' => $staffs->random()->id, 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, 'tanggal_selesai' => $status === 'Selesai' ? now() : null, 'status' => $status diff --git a/database/factories/OrderFactory.php b/database/factories/OrderFactory.php index f41ffee..4af7daf 100644 --- a/database/factories/OrderFactory.php +++ b/database/factories/OrderFactory.php @@ -4,6 +4,9 @@ use Illuminate\Database\Eloquent\Factories\Factory; +use App\Models\Customer; +use App\Models\Product; + /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Order> */ @@ -19,10 +22,12 @@ public function definition(): array $price = fake()->numberBetween(1000000, 10000000); $paid = fake()->numberBetween(1000000, $price); $order_date = fake()->dateTimeBetween('-6 months', 'now'); + $customers = Customer::inRandomOrder()->first(); + $products = Product::inRandomOrder()->first(); return [ - 'customer_id' => fake()->numberBetween(1, 10), + 'customer_id' => $customers->id, 'order_date' => $order_date, - 'product_id' => fake()->numberBetween(1, 10), + 'product_id' => $products->id, 'price' => $price, 'payment_method' => fake()->randomElement(['Tunai', 'Transfer']), 'paid' => $paid, diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index b1ea0dc..0835d93 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -12,7 +12,7 @@ public function run() { User::factory()->create([ 'name' => 'Test Admin', - 'email' => 'test@larapi.test', + 'email' => 'user1@asistennotaris.com', 'is_admin' => true, 'avatar' => null, 'phone' => '08123456789', @@ -20,36 +20,47 @@ public function run() 'position' => 'Manager', 'password' => Hash::make('password'), ]); - // User::factory()->create([ - // 'name' => 'Test Manager', - // 'email' => 'manager@larapi.test', - // 'is_admin' => false, - // 'avatar' => null, - // 'phone' => '08123456789', - // 'address' => 'Jl. Kebon Jeruk No. 1', - // 'position' => 'Manager', - // 'password' => Hash::make('password'), - // ]); - // User::factory()->create([ - // 'name' => 'Test Keuangan', - // 'email' => 'keuangan@larapi.test', - // 'is_admin' => false, - // 'avatar' => null, - // 'phone' => '08123456789', - // 'address' => 'Jl. Kebon Jeruk No. 1', - // 'position' => 'Keuangan', - // 'password' => Hash::make('password'), - // ]); - // User::factory()->create([ - // 'name' => 'Test Staff', - // 'email' => 'staff@larapi.test', - // 'is_admin' => false, - // 'avatar' => null, - // 'phone' => '08123456789', - // 'address' => 'Jl. Kebon Jeruk No. 1', - // 'position' => 'Staff', - // 'password' => Hash::make('password'), - // ]); + User::factory()->create([ + 'name' => 'Test Manager', + 'email' => 'user2@asistennotaris.com', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Manager', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test Keuangan', + 'email' => 'user3@asistennotaris.com', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Keuangan', + 'password' => Hash::make('password'), + ]); + User::factory()->create([ + 'name' => 'Test Staff', + 'email' => 'user4@asistennotaris.com', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Staff', + 'password' => Hash::make('password'), + ]); + + User::factory()->create([ + 'name' => 'Test Staff 2', + 'email' => 'user5@asistennotaris.com', + 'is_admin' => false, + 'avatar' => null, + 'phone' => '08123456789', + 'address' => 'Jl. Kebon Jeruk No. 1', + 'position' => 'Staff', + 'password' => Hash::make('password'), + ]); // // Membuat 30 pengguna // User::factory(6)->create(); From 04e09b9645c72a15e3cc779377e53321e427f6f9 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 10 Feb 2025 13:08:08 +0700 Subject: [PATCH 118/184] add build feature --- .gitignore | 1 + package-lock.json | 1896 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 13 + src/script.js | 86 ++ 4 files changed, 1996 insertions(+) create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/script.js diff --git a/.gitignore b/.gitignore index fc2b090..823509a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ /storage/*.key /storage/pail /vendor +/dist .env .env.backup .env.production diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..bf4fcb1 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1896 @@ +{ + "name": "larapi", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "larapi", + "version": "1.0.0", + "dependencies": { + "archiver": "^7.0.1" + }, + "devDependencies": { + "zip-cli": "^0.0.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@oclif/command": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.36.tgz", + "integrity": "sha512-/zACSgaYGtAQRzc7HjzrlIs14FuEYAZrMOEwicRoUnZVyRunG4+t5iSEeQu0Xy2bgbCD0U1SP/EdeNZSTXRwjQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/config": "^1.18.2", + "@oclif/errors": "^1.3.6", + "@oclif/help": "^1.0.1", + "@oclif/parser": "^3.8.17", + "debug": "^4.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "@oclif/config": "^1" + } + }, + "node_modules/@oclif/config": { + "version": "1.18.17", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.17.tgz", + "integrity": "sha512-k77qyeUvjU8qAJ3XK3fr/QVAqsZO8QOBuESnfeM5HHtPNLSyfVcwiMM2zveSW5xRdLSG3MfV8QnLVkuyCL2ENg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/errors": "^1.3.6", + "@oclif/parser": "^3.8.17", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-wsl": "^2.1.1", + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/config/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@oclif/errors": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.6.tgz", + "integrity": "sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^3.0.0", + "fs-extra": "^8.1", + "indent-string": "^4.0.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/help": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@oclif/help/-/help-1.0.15.tgz", + "integrity": "sha512-Yt8UHoetk/XqohYX76DfdrUYLsPKMc5pgkzsZVHDyBSkLiGRzujVaGZdjr32ckVZU9q3a47IjhWxhip7Dz5W/g==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/config": "1.18.16", + "@oclif/errors": "1.3.6", + "chalk": "^4.1.2", + "indent-string": "^4.0.0", + "lodash": "^4.17.21", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "widest-line": "^3.1.0", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/help/node_modules/@oclif/config": { + "version": "1.18.16", + "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.16.tgz", + "integrity": "sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/errors": "^1.3.6", + "@oclif/parser": "^3.8.16", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-wsl": "^2.1.1", + "tslib": "^2.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/help/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@oclif/help/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@oclif/linewrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz", + "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==", + "dev": true, + "license": "ISC" + }, + "node_modules/@oclif/parser": { + "version": "3.8.17", + "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.17.tgz", + "integrity": "sha512-l04iSd0xoh/16TGVpXb81Gg3z7tlQGrEup16BrVLsZBK6SEYpYHRJZnM32BwZrHI97ZSFfuSwVlzoo6HdsaK8A==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/errors": "^1.3.6", + "@oclif/linewrap": "^1.0.0", + "chalk": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/parser/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/@oclif/plugin-help": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.3.tgz", + "integrity": "sha512-bGHUdo5e7DjPJ0vTeRBMIrfqTRDBfyR5w0MP41u0n3r7YG5p14lvMmiCXxi6WDaP2Hw5nqx3PnkAIntCKZZN7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/command": "^1.5.13", + "chalk": "^2.4.1", + "indent-string": "^4.0.0", + "lodash.template": "^4.4.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0", + "widest-line": "^2.0.1", + "wrap-ansi": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@oclif/plugin-help/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@oclif/plugin-help/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@oclif/plugin-help/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@oclif/plugin-help/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@oclif/plugin-help/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@oclif/plugin-help/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@oclif/plugin-help/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@oclif/plugin-help/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", + "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", + "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" + }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "license": "Apache-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/clean-stack": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", + "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", + "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/streamx": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/zip-cli": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/zip-cli/-/zip-cli-0.0.0.tgz", + "integrity": "sha512-vWxzpzIf57HcDFfChNT25riZH6tOjcouizS0fUt33VkZ96hzWHrstTgAUpBghY4YnQAXg6k+EODQf2mcnppTEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oclif/command": "^1.5.19", + "@oclif/config": "^1.14.0", + "@oclif/plugin-help": "^2.2.3", + "adm-zip": "^0.4.14", + "tslib": "^1.10.0" + }, + "bin": { + "zip-cli": "bin/run" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..faa82d4 --- /dev/null +++ b/package.json @@ -0,0 +1,13 @@ +{ + "name": "larapi", + "version": "1.0.0", + "description": "Aplikasi Laravel untuk API", + "main": "index.js", + "scripts": { + "build": "node src/script.js" + }, + "dependencies": { + "archiver": "^5.3.1", + "fs": "0.0.1-security" + } +} diff --git a/src/script.js b/src/script.js new file mode 100644 index 0000000..9620de2 --- /dev/null +++ b/src/script.js @@ -0,0 +1,86 @@ +const fs = require("fs"); +const path = require("path"); +const archiver = require("archiver"); + +// Buat folder `dist` jika belum ada +const distDir = path.join(__dirname, "../dist"); +if (!fs.existsSync(distDir)) { + fs.mkdirSync(distDir); +} + +// Nama file ZIP yang akan dihasilkan +const output = fs.createWriteStream(path.join(distDir, "laravel-app.zip")); +const archive = archiver("zip", { + zlib: { level: 9 }, // Tingkat kompresi maksimal +}); + +// Event listener untuk ketika file ZIP selesai dibuat +output.on("close", function () { + console.log( + "File ZIP berhasil dibuat: " + archive.pointer() + " total bytes" + ); + console.log( + `File ZIP disimpan di: ${path.join(distDir, "laravel-app.zip")}` + ); +}); + +// Event listener untuk menangani error +archive.on("error", function (err) { + throw err; +}); + +// Mulai proses kompresi +archive.pipe(output); + +// Direktori root Laravel +const laravelDir = path.join(__dirname, ".."); // Sesuaikan dengan struktur direktori Anda + +// Daftar file dan folder yang akan diabaikan +const ignoreList = [ + ".vscode", + ".git", + ".env", + "package.json", + "package-lock.json", + "node_modules", + "storage", + "vendor", + "dist", + "laravel-app.zip", + ".github", + "composer.lock", + "composer.json", +]; + +// Fungsi untuk menambahkan file dan folder ke ZIP +function addDirectoryToArchive(dir, prefix = "") { + const files = fs.readdirSync(dir); + + files.forEach((file) => { + const filePath = path.join(dir, file); + const relativePath = prefix ? `${prefix}/${file}` : file; + + // Cek apakah file/folder harus diabaikan + if (ignoreList.includes(file)) { + console.log(`Mengabaikan: ${relativePath}`); + return; + } + + const stat = fs.statSync(filePath); + + if (stat.isDirectory()) { + // Tambahkan direktori ke ZIP + addDirectoryToArchive(filePath, relativePath); + } else { + // Tambahkan file ke ZIP + archive.file(filePath, { name: relativePath }); + console.log(`Menambahkan: ${relativePath}`); + } + }); +} + +// Mulai proses menambahkan file dan folder ke ZIP +addDirectoryToArchive(laravelDir); + +// Finalisasi proses kompresi +archive.finalize(); From 7225eb6c82321538aa2f5a32d390d171d3012450 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 13 Feb 2025 08:45:51 +0700 Subject: [PATCH 119/184] fix email notification --- app/Notifications/NewOrderNotification.php | 30 +++++----------------- resources/views/emails/new_order.blade.php | 16 ++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) create mode 100644 resources/views/emails/new_order.blade.php diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index 44fed89..c9e46c8 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -2,25 +2,18 @@ namespace App\Notifications; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Support\Facades\View; use Illuminate\Notifications\Notification; use App\Models\Setting; -use Illuminate\Support\Facades\Log; - -class NewOrderNotification extends Notification implements ShouldQueue +class NewOrderNotification extends Notification { - use Queueable; - protected $message; protected $order; /** * Buat instance notifikasi baru. - * - * Ambil pesan dari pengaturan. */ public function __construct($order) { @@ -55,36 +48,27 @@ public function __construct($order) /** * Tentukan saluran mana yang akan digunakan untuk mengirim notifikasi. - * - * @param mixed $notifiable - * @return array */ public function via($notifiable) { - return ['mail', 'database']; // Anda bisa menambahkan saluran lain seperti database, broadcast, dsb. + return ['mail', 'database']; } /** * Siapkan pesan email untuk notifikasi. - * - * @param mixed $notifiable - * @return MailMessage */ public function toMail($notifiable) { return (new MailMessage) ->subject('Notifikasi Pesanan Baru') - ->line($this->message) - ->line('Tanggal Pesanan: ' . $this->order->order_date) - ->action('Lihat Pesanan', url('/orders')) - ->line('Terima kasih telah menggunakan aplikasi kami!'); + ->view('emails.new_order', [ + 'messageContent' => $this->message, // Ubah key agar tidak bentrok + 'order' => $this->order + ]); } /** * Siapkan pesan database untuk notifikasi. - * - * @param mixed $notifiable - * @return array */ public function toDatabase($notifiable) { diff --git a/resources/views/emails/new_order.blade.php b/resources/views/emails/new_order.blade.php new file mode 100644 index 0000000..d84814b --- /dev/null +++ b/resources/views/emails/new_order.blade.php @@ -0,0 +1,16 @@ + + + + + + + Notifikasi Pesanan Baru + + + + {!! $messageContent !!} +
+

Terima kasih!

+ + + \ No newline at end of file From 0c00f6dc55f40fca066a5d19ac1abe0b84a0b785 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 13 Feb 2025 11:52:27 +0700 Subject: [PATCH 120/184] fix email notification --- .../Controllers/NotificationController.php | 32 +++++++++++++++++++ routes/api.php | 3 ++ 2 files changed, 35 insertions(+) diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php index a4699c8..c94e027 100644 --- a/app/Http/Controllers/NotificationController.php +++ b/app/Http/Controllers/NotificationController.php @@ -5,6 +5,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; + class NotificationController extends Controller { public function index() @@ -20,4 +21,35 @@ public function update($id) return response()->json($notification); } + + public function read($id) + { + $notification = Auth::user()->notifications()->find($id); + $notification->markAsRead(); + + return response()->json($notification); + } + + public function readAll() + { + $notifications = Auth::user()->notifications()->get(); + $notifications->each(function ($notification) { + $notification->markAsRead(); + }); + + return response()->json($notifications); + } + public function unread() + { + $notifications = Auth::user()->unreadNotifications->map(function ($data) { + return [ + + 'id' => $data->id, + 'message' => $data->data['message'], + 'time' => $data->created_at + ]; + }); + + return response()->json($notifications); + } } diff --git a/routes/api.php b/routes/api.php index d4caf07..a527c4b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,6 +26,9 @@ Route::get('home', [DashboardController::class, 'index']); Route::get('notifications', [NotificationController::class, 'index']); Route::put('notifications/{id}', [NotificationController::class, 'update']); + Route::put('notifications/read/{id}', [NotificationController::class, 'read']); + Route::put('notifications/read-all', [NotificationController::class, 'readAll']); + Route::get('notifications/unread', [NotificationController::class, 'unread']); Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From 0e7f3fa6af9417798e3fc70392acac43c9bbf1cc Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 13 Feb 2025 13:59:18 +0700 Subject: [PATCH 121/184] set url in notification --- app/Http/Controllers/NotificationController.php | 7 +++++-- app/Notifications/NewOrderNotification.php | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/NotificationController.php b/app/Http/Controllers/NotificationController.php index c94e027..06c779b 100644 --- a/app/Http/Controllers/NotificationController.php +++ b/app/Http/Controllers/NotificationController.php @@ -43,10 +43,13 @@ public function unread() { $notifications = Auth::user()->unreadNotifications->map(function ($data) { return [ - 'id' => $data->id, 'message' => $data->data['message'], - 'time' => $data->created_at + 'time' => $data->created_at, + 'url' => isset($data->data['order']['customer']['id']) + ? '/order?konsumen_id=' . $data->data['order']['customer']['id'] + : null, + 'order_id' => $data->data['order']['id'] ?? null ]; }); diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index c9e46c8..d47cb5b 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -51,7 +51,7 @@ public function __construct($order) */ public function via($notifiable) { - return ['mail', 'database']; + return ['database']; //'mail', 'database' } /** @@ -75,6 +75,7 @@ public function toDatabase($notifiable) return [ 'message' => 'Pesanan baru telah diterima dari ' . $this->order->customer->name, 'notifiable' => $notifiable, + 'order' => $this->order ]; } } From eb1ccc7f089455f891f8a81fccb49d20587a2071 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 13 Feb 2025 15:22:18 +0700 Subject: [PATCH 122/184] jobdesk notification --- app/Notifications/NewOrderNotification.php | 2 +- app/Notifications/PendingJobdesk.php | 59 +++++++++++-------- .../views/emails/pending_jobdesk.blade.php | 16 +++++ 3 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 resources/views/emails/pending_jobdesk.blade.php diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index d47cb5b..5a52a41 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -62,7 +62,7 @@ public function toMail($notifiable) return (new MailMessage) ->subject('Notifikasi Pesanan Baru') ->view('emails.new_order', [ - 'messageContent' => $this->message, // Ubah key agar tidak bentrok + 'messageContent' => $this->message, 'order' => $this->order ]); } diff --git a/app/Notifications/PendingJobdesk.php b/app/Notifications/PendingJobdesk.php index 27ae109..c3a1bae 100644 --- a/app/Notifications/PendingJobdesk.php +++ b/app/Notifications/PendingJobdesk.php @@ -2,59 +2,72 @@ namespace App\Notifications; -use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Notifications\Notification; +use App\Models\Setting; class PendingJobdesk extends Notification { - use Queueable; + protected $message; + protected $data; /** - * Create a new notification instance. + * Buat instance notifikasi baru. */ - protected $data; - public function __construct($data) { + // Ambil pesan dari pengaturan, jika ada + $this->message = Setting::where('setting_key', 'pending_jobdesk')->value('setting_value') ?? 'Pesan default jika tidak ada setting'; + + // Simpan data jobdesk $this->data = $data; + + $this->message = str_replace( + [ + '[nama_klien]', + '[jobdesk_id]', + '[tim_manajemen]', + ], + [ + $data['client_name'], + $data['jobdesk_id'], + 'Tim Manajemen ' . Setting::where('setting_key', 'app_name')->value('setting_value'), + ], + $this->message + ); } /** - * Get the notification's delivery channels. - * - * @return array + * Tentukan saluran mana yang akan digunakan untuk mengirim notifikasi. */ - public function via(object $notifiable): array + public function via($notifiable) { - return ['mail', 'database']; + return ['mail', 'database']; //'mail', 'database' } /** - * Get the mail representation of the notification. + * Siapkan pesan email untuk notifikasi. */ public function toMail($notifiable) { return (new MailMessage) ->subject('Pemberitahuan: Jobdesk Belum Diambil') - ->greeting('Halo ' . $notifiable->name . '!') - ->line('Kami ingin mengingatkan Anda bahwa ada jobdesk yang belum Anda ambil:') - ->line('Jobdesk: ' . $this->data['jobdesk_id']) - ->action('Ambil Jobdesk', url('/jobdesk/' . $this->data['jobdesk_id'])) - ->line('Terima kasih atas perhatian Anda!'); + ->view('emails.pending_jobdesk', [ + 'messageContent' => $this->message, + 'data' => $this->data, + 'notifiable' => $notifiable, + ]); } /** - * Get the array representation of the notification. - * - * @return array + * Siapkan pesan database untuk notifikasi. */ - public function toArray(object $notifiable): array + public function toDatabase($notifiable) { return [ - 'jobdesk' => $this->data['jobdesk_id'], - 'message' => 'Pemberitahuan: Jobdesk #' . $this->data['jobdesk_id'] . ' Belum Diambil' + 'message' => 'Jobdesk #' . $this->data['jobdesk_id'] . ' belum diambil oleh ' . $notifiable->name, + 'notifiable' => $notifiable, + 'jobdesk' => $this->data ]; } } diff --git a/resources/views/emails/pending_jobdesk.blade.php b/resources/views/emails/pending_jobdesk.blade.php new file mode 100644 index 0000000..c16f13b --- /dev/null +++ b/resources/views/emails/pending_jobdesk.blade.php @@ -0,0 +1,16 @@ + + + + + + + Pemberitahuan: Jobdesk Belum Diambil + + + + {!! $messageContent !!} +
+

Terima kasih!

+ + + \ No newline at end of file From 396eed5c3a6e514554137702a7c420bb0f7deb00 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 13 Feb 2025 22:34:32 +0700 Subject: [PATCH 123/184] ignore package-lock.json --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 823509a..f263447 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ Homestead.yaml auth.json npm-debug.log yarn-error.log +package-lock.json vscode /.fleet /.idea From 1d69f953dc4c9827ddf265e01b0fac25590a7abe Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 15 Feb 2025 10:57:22 +0700 Subject: [PATCH 124/184] fix order kosong saat undefine --- app/Http/Controllers/OrderController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 329b5a0..ef3cb75 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -35,7 +35,7 @@ public function index(Request $request) $query = Order::with('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); - if ($customerId) { + if (isset($customerId) && $customerId !== 'undefined') { $query->where('customer_id', $customerId); } From 94d1e2ad4fe5043839f268f8fa965ca46f84f2b7 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 17 Feb 2025 19:34:50 +0700 Subject: [PATCH 125/184] menambah meta customer --- app/Models/Customer.php | 5 +++ app/Models/CustomerMeta.php | 25 ++++++++++++++ ...2_17_193026_create_customer_meta_table.php | 33 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 app/Models/CustomerMeta.php create mode 100644 database/migrations/2025_02_17_193026_create_customer_meta_table.php diff --git a/app/Models/Customer.php b/app/Models/Customer.php index abe344b..77f8d45 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -19,4 +19,9 @@ public function orders() { return $this->hasMany(Order::class); } + + public function meta() + { + return $this->hasMany(CustomerMeta::class); + } } diff --git a/app/Models/CustomerMeta.php b/app/Models/CustomerMeta.php new file mode 100644 index 0000000..941dec8 --- /dev/null +++ b/app/Models/CustomerMeta.php @@ -0,0 +1,25 @@ +belongsTo(Customer::class); + } +} diff --git a/database/migrations/2025_02_17_193026_create_customer_meta_table.php b/database/migrations/2025_02_17_193026_create_customer_meta_table.php new file mode 100644 index 0000000..27179c0 --- /dev/null +++ b/database/migrations/2025_02_17_193026_create_customer_meta_table.php @@ -0,0 +1,33 @@ +id(); + $table->unsignedBigInteger('customer_id'); + $table->string('meta_key'); + $table->text('meta_value')->nullable(); + $table->timestamps(); + + // Menambahkan foreign key constraint + $table->foreign('customer_id')->references('id')->on('customers')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('customer_meta'); + } +}; From 362deb3e06ecda52e4917c7a15f48bb201f05ec6 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 17 Feb 2025 20:59:01 +0700 Subject: [PATCH 126/184] add permision controller --- app/Http/Controllers/PermissionController.php | 22 + package-lock.json | 1787 +++-------------- routes/api.php | 4 +- 3 files changed, 257 insertions(+), 1556 deletions(-) create mode 100644 app/Http/Controllers/PermissionController.php diff --git a/app/Http/Controllers/PermissionController.php b/app/Http/Controllers/PermissionController.php new file mode 100644 index 0000000..ba131e2 --- /dev/null +++ b/app/Http/Controllers/PermissionController.php @@ -0,0 +1,22 @@ +json($permissions); + } + + public function update(Request $request, User $user) + { + $permissions = $request->input('permissions'); + $user->syncPermissions($permissions); // Menggunakan Spatie + return response()->json(['message' => 'Permissions updated']); + } +} diff --git a/package-lock.json b/package-lock.json index bf4fcb1..cbf842d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,661 +8,77 @@ "name": "larapi", "version": "1.0.0", "dependencies": { - "archiver": "^7.0.1" - }, - "devDependencies": { - "zip-cli": "^0.0.0" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@oclif/command": { - "version": "1.8.36", - "resolved": "https://registry.npmjs.org/@oclif/command/-/command-1.8.36.tgz", - "integrity": "sha512-/zACSgaYGtAQRzc7HjzrlIs14FuEYAZrMOEwicRoUnZVyRunG4+t5iSEeQu0Xy2bgbCD0U1SP/EdeNZSTXRwjQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "dependencies": { - "@oclif/config": "^1.18.2", - "@oclif/errors": "^1.3.6", - "@oclif/help": "^1.0.1", - "@oclif/parser": "^3.8.17", - "debug": "^4.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "@oclif/config": "^1" - } - }, - "node_modules/@oclif/config": { - "version": "1.18.17", - "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.17.tgz", - "integrity": "sha512-k77qyeUvjU8qAJ3XK3fr/QVAqsZO8QOBuESnfeM5HHtPNLSyfVcwiMM2zveSW5xRdLSG3MfV8QnLVkuyCL2ENg==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "dependencies": { - "@oclif/errors": "^1.3.6", - "@oclif/parser": "^3.8.17", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-wsl": "^2.1.1", - "tslib": "^2.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/config/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@oclif/errors": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/@oclif/errors/-/errors-1.3.6.tgz", - "integrity": "sha512-fYaU4aDceETd89KXP+3cLyg9EHZsLD3RxF2IU9yxahhBpspWjkWi3Dy3bTgcwZ3V47BgxQaGapzJWDM33XIVDQ==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^3.0.0", - "fs-extra": "^8.1", - "indent-string": "^4.0.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/help": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/@oclif/help/-/help-1.0.15.tgz", - "integrity": "sha512-Yt8UHoetk/XqohYX76DfdrUYLsPKMc5pgkzsZVHDyBSkLiGRzujVaGZdjr32ckVZU9q3a47IjhWxhip7Dz5W/g==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "dependencies": { - "@oclif/config": "1.18.16", - "@oclif/errors": "1.3.6", - "chalk": "^4.1.2", - "indent-string": "^4.0.0", - "lodash": "^4.17.21", - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "widest-line": "^3.1.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/help/node_modules/@oclif/config": { - "version": "1.18.16", - "resolved": "https://registry.npmjs.org/@oclif/config/-/config-1.18.16.tgz", - "integrity": "sha512-VskIxVcN22qJzxRUq+raalq6Q3HUde7sokB7/xk5TqRZGEKRVbFeqdQBxDWwQeudiJEgcNiMvIFbMQ43dY37FA==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "dependencies": { - "@oclif/errors": "^1.3.6", - "@oclif/parser": "^3.8.16", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-wsl": "^2.1.1", - "tslib": "^2.6.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/help/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@oclif/help/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@oclif/linewrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@oclif/linewrap/-/linewrap-1.0.0.tgz", - "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==", - "dev": true, - "license": "ISC" - }, - "node_modules/@oclif/parser": { - "version": "3.8.17", - "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.17.tgz", - "integrity": "sha512-l04iSd0xoh/16TGVpXb81Gg3z7tlQGrEup16BrVLsZBK6SEYpYHRJZnM32BwZrHI97ZSFfuSwVlzoo6HdsaK8A==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "dependencies": { - "@oclif/errors": "^1.3.6", - "@oclif/linewrap": "^1.0.0", - "chalk": "^4.1.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/parser/node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/@oclif/plugin-help": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-2.2.3.tgz", - "integrity": "sha512-bGHUdo5e7DjPJ0vTeRBMIrfqTRDBfyR5w0MP41u0n3r7YG5p14lvMmiCXxi6WDaP2Hw5nqx3PnkAIntCKZZN7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oclif/command": "^1.5.13", - "chalk": "^2.4.1", - "indent-string": "^4.0.0", - "lodash.template": "^4.4.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0", - "widest-line": "^2.0.1", - "wrap-ansi": "^4.0.0" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@oclif/plugin-help/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@oclif/plugin-help/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@oclif/plugin-help/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@oclif/plugin-help/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@oclif/plugin-help/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@oclif/plugin-help/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@oclif/plugin-help/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^2.1.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/widest-line/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", - "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@oclif/plugin-help/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "license": "MIT", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.3.0" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "archiver": "^5.3.1", + "fs": "0.0.1-security" } }, "node_modules/archiver": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", - "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.2.tgz", + "integrity": "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==", "license": "MIT", "dependencies": { - "archiver-utils": "^5.0.2", + "archiver-utils": "^2.1.0", "async": "^3.2.4", - "buffer-crc32": "^1.0.0", - "readable-stream": "^4.0.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", "readdir-glob": "^1.1.2", - "tar-stream": "^3.0.0", - "zip-stream": "^6.0.1" + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" }, "engines": { - "node": ">= 14" + "node": ">= 10" } }, "node_modules/archiver-utils": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", - "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", "license": "MIT", "dependencies": { - "glob": "^10.0.0", + "glob": "^7.1.4", "graceful-fs": "^4.2.0", - "is-stream": "^2.0.1", "lazystream": "^1.0.0", - "lodash": "^4.17.15", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" + "readable-stream": "^2.0.0" }, "engines": { - "node": ">= 14" + "node": ">= 6" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/archiver-utils/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/archiver-utils/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" } }, "node_modules/async": { @@ -671,25 +87,12 @@ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", "license": "MIT" }, - "node_modules/b4a": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", - "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", - "license": "Apache-2.0" - }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "license": "MIT" }, - "node_modules/bare-events": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", - "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", - "license": "Apache-2.0", - "optional": true - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -710,6 +113,17 @@ ], "license": "MIT" }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -719,23 +133,10 @@ "balanced-match": "^1.0.0" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "funding": [ { "type": "github", @@ -753,85 +154,39 @@ "license": "MIT", "dependencies": { "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "ieee754": "^1.1.13" } }, "node_modules/buffer-crc32": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", - "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "license": "MIT", "engines": { - "node": ">=8.0.0" + "node": "*" } }, - "node_modules/chalk": { + "node_modules/compress-commons": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.2.tgz", + "integrity": "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/clean-stack": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-3.0.1.tgz", - "integrity": "sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 10" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "license": "MIT" }, - "node_modules/compress-commons": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", - "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", - "license": "MIT", - "dependencies": { - "crc-32": "^1.2.0", - "crc32-stream": "^6.0.0", - "is-stream": "^2.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -851,235 +206,64 @@ } }, "node_modules/crc32-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", - "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.3.tgz", + "integrity": "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==", "license": "MIT", "dependencies": { "crc-32": "^1.2.0", - "readable-stream": "^4.0.0" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" + "readable-stream": "^3.4.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 10" } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", "license": "MIT", "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "once": "^1.4.0" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==", + "license": "ISC" }, - "node_modules/fast-fifo": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", - "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", - "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" }, "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "license": "ISC", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=10" + "node": "*" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/graceful-fs": { @@ -1088,16 +272,6 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1106,164 +280,41 @@ { "type": "github", "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "license": "MIT", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" + "once": "^1.3.0", + "wrappy": "1" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, "node_modules/isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "license": "MIT" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, "node_modules/lazystream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", @@ -1306,102 +357,58 @@ "safe-buffer": "~5.1.0" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA==", - "dev": true, + "node_modules/lodash.defaults": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", "license": "MIT" }, - "node_modules/lodash.template": { + "node_modules/lodash.difference": { "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "node_modules/lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash._reinterpolate": "^3.0.0" - } + "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", + "license": "MIT" }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" + "node_modules/lodash.flatten": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", + "license": "MIT" }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } + "node_modules/lodash.union": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", + "license": "MIT" }, "node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": "*" } }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -1411,67 +418,22 @@ "node": ">=0.10.0" } }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "license": "BlueOak-1.0.0" - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "license": "BlueOak-1.0.0", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "wrappy": "1" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "license": "MIT", "engines": { - "node": ">= 0.6.0" + "node": ">=0.10.0" } }, "node_modules/process-nextick-args": { @@ -1480,41 +442,18 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/readable-stream": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", - "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 6" } }, "node_modules/readdir-glob": { @@ -1538,41 +477,6 @@ "node": ">=10" } }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1593,75 +497,6 @@ ], "license": "MIT" }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/streamx": { - "version": "2.22.0", - "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", - "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", - "license": "MIT", - "dependencies": { - "fast-fifo": "^1.3.2", - "text-decoder": "^1.1.0" - }, - "optionalDependencies": { - "bare-events": "^2.2.0" - } - }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -1671,121 +506,20 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/tar-stream": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", - "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", - "license": "MIT", - "dependencies": { - "b4a": "^1.6.4", - "fast-fifo": "^1.2.0", - "streamx": "^2.15.0" - } - }, - "node_modules/text-decoder": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", - "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", - "license": "Apache-2.0", - "dependencies": { - "b4a": "^1.6.4" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", "license": "MIT", "dependencies": { - "is-number": "^7.0.0" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" }, "engines": { - "node": ">=8.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" + "node": ">=6" } }, "node_modules/util-deprecate": { @@ -1794,102 +528,45 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, - "node_modules/zip-cli": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/zip-cli/-/zip-cli-0.0.0.tgz", - "integrity": "sha512-vWxzpzIf57HcDFfChNT25riZH6tOjcouizS0fUt33VkZ96hzWHrstTgAUpBghY4YnQAXg6k+EODQf2mcnppTEA==", - "dev": true, + "node_modules/zip-stream": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.1.tgz", + "integrity": "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==", "license": "MIT", "dependencies": { - "@oclif/command": "^1.5.19", - "@oclif/config": "^1.14.0", - "@oclif/plugin-help": "^2.2.3", - "adm-zip": "^0.4.14", - "tslib": "^1.10.0" - }, - "bin": { - "zip-cli": "bin/run" + "archiver-utils": "^3.0.4", + "compress-commons": "^4.1.2", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">=8.0.0" + "node": ">= 10" } }, - "node_modules/zip-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", - "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "node_modules/zip-stream/node_modules/archiver-utils": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-3.0.4.tgz", + "integrity": "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==", "license": "MIT", "dependencies": { - "archiver-utils": "^5.0.0", - "compress-commons": "^6.0.2", - "readable-stream": "^4.0.0" + "glob": "^7.2.3", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">= 14" + "node": ">= 10" } } } diff --git a/routes/api.php b/routes/api.php index a527c4b..344a16f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -14,7 +14,7 @@ use App\Http\Controllers\SendNotificationController; use App\Http\Controllers\Auth\ProfileController; use App\Http\Controllers\NotificationController; - +use App\Http\Controllers\PermissionController; Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { @@ -29,6 +29,8 @@ Route::put('notifications/read/{id}', [NotificationController::class, 'read']); Route::put('notifications/read-all', [NotificationController::class, 'readAll']); Route::get('notifications/unread', [NotificationController::class, 'unread']); + Route::get('/permissions', [PermissionController::class, 'index']); + Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From 7624c7804d03395320ef30b16c4efb0bce25c073 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 18 Feb 2025 11:24:25 +0700 Subject: [PATCH 127/184] add controller bank --- .../Controllers/BankSettingController.php | 50 ++++++++++++ database/seeders/DatabaseSeeder.php | 75 +----------------- database/seeders/SettingSeeder.php | 76 ++++++++++++++++++- routes/api.php | 7 ++ 4 files changed, 134 insertions(+), 74 deletions(-) create mode 100644 app/Http/Controllers/BankSettingController.php diff --git a/app/Http/Controllers/BankSettingController.php b/app/Http/Controllers/BankSettingController.php new file mode 100644 index 0000000..7f39cb6 --- /dev/null +++ b/app/Http/Controllers/BankSettingController.php @@ -0,0 +1,50 @@ +first(); + $banks = $setting ? json_decode($setting->setting_value, true) : []; + + return response()->json($banks); + } + + /** + * Store or update the bank settings. + */ + public function store(Request $request) + { + $validatedData = $request->validate([ + 'banks' => 'required|array', + 'banks.*.name' => 'required|string|max:255', + ]); + + $banksJson = json_encode($validatedData['banks']); + + Setting::updateOrCreate( + ['setting_key' => 'banks'], + ['setting_value' => $banksJson] + ); + + return response()->json(['message' => 'Bank settings saved successfully.']); + } + + /** + * Remove the bank settings. + */ + public function destroy() + { + Setting::where('setting_key', 'banks')->delete(); + + return response()->json(['message' => 'Bank settings deleted successfully.']); + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index acb24b9..de52d72 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -17,11 +17,11 @@ public function run(): void { $this->call([ + SettingSeeder::class, UserSeeder::class, ProductSeeder::class, ]); - // Seed settings first - $this->seedSettings(); + // Seed customers and orders $customers = Customer::factory(28)->create(); @@ -37,75 +37,4 @@ public function run(): void } } } - - protected function seedSettings() - { - $template_order = ' - Pemberitahuan Order Layanan Notaris Baru
-
- Tanggal: [tanggal_order]
-
- Detail Order:
- ======================================
- Nama Klien: [nama_klien]
- Nomor Telepon: [no_telp]
- Jenis Layanan Notaris: [product]
- ======================================
-
- Harap segera follow up order ini ke staff terkait.
-
- Terima kasih.
- [tim_manajemen] - '; - $template_project = ' - Pemberitahuan Penugasan Proyek
-
- Tanggal: [tanggal_penugasan]
-
- Detail Proyek:
- ======================================
- Nama Proyek: [nama_proyek]
- Deskripsi: [description_proyek]
- Batas Waktu: [batas_waktu]
- Penanggung Jawab: [nama_superadmin]
- ======================================
-
- Harap segera mulai bekerja pada proyek ini dan laporkan perkembangan secara berkala.
-
- Terima kasih.
- [tim_manajemen] - '; - $template_followup = ' - Follow-Up Proyek
-
- Tanggal: [tanggal_followup]
-
- Detail Proyek:
- ======================================
- Nama Proyek: [nama_proyek]
- Penanggung Jawab: [nama_karyawan]
- Batas Waktu: [batas_waktu]
- Status Terakhir: [status_terakhir]
- ======================================
-
- Harap berikan update mengenai perkembangan proyek ini dan jika ada kendala, silakan laporkan segera.
-
- Terima kasih.
- [tim_manajemen] - '; - $templates = [ - ['setting_key' => 'new_order', 'setting_value' => $template_order], - ['setting_key' => 'project_assignment', 'setting_value' => $template_project], - ['setting_key' => 'followup_project', 'setting_value' => $template_followup], - - ['setting_key' => 'app_name', 'setting_value' => 'APP'], - ['setting_key' => 'app_code', 'setting_value' => 'AN'], - ['setting_key' => 'app_description', 'setting_value' => 'Asisten Notaris Online'], - ['setting_key' => 'address', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], - ['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf'], - ['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com'], - ]; - - Setting::insert($templates); // Batch insert - } } diff --git a/database/seeders/SettingSeeder.php b/database/seeders/SettingSeeder.php index 9a6d9b6..c143ae0 100644 --- a/database/seeders/SettingSeeder.php +++ b/database/seeders/SettingSeeder.php @@ -4,6 +4,7 @@ use Illuminate\Database\Console\Seeds\WithoutModelEvents; use Illuminate\Database\Seeder; +use App\Models\Setting; class SettingSeeder extends Seeder { @@ -12,6 +13,79 @@ class SettingSeeder extends Seeder */ public function run(): void { - // + $template_order = ' + Pemberitahuan Order Layanan Notaris Baru
+
+ Tanggal: [tanggal_order]
+
+ Detail Order:
+ ======================================
+ Nama Klien: [nama_klien]
+ Nomor Telepon: [no_telp]
+ Jenis Layanan Notaris: [product]
+ ======================================
+
+ Harap segera follow up order ini ke staff terkait.
+
+ Terima kasih.
+ [tim_manajemen] + '; + $template_project = ' + Pemberitahuan Penugasan Proyek
+
+ Tanggal: [tanggal_penugasan]
+
+ Detail Proyek:
+ ======================================
+ Nama Proyek: [nama_proyek]
+ Deskripsi: [description_proyek]
+ Batas Waktu: [batas_waktu]
+ Penanggung Jawab: [nama_superadmin]
+ ======================================
+
+ Harap segera mulai bekerja pada proyek ini dan laporkan perkembangan secara berkala.
+
+ Terima kasih.
+ [tim_manajemen] + '; + $template_followup = ' + Follow-Up Proyek
+
+ Tanggal: [tanggal_followup]
+
+ Detail Proyek:
+ ======================================
+ Nama Proyek: [nama_proyek]
+ Penanggung Jawab: [nama_karyawan]
+ Batas Waktu: [batas_waktu]
+ Status Terakhir: [status_terakhir]
+ ======================================
+
+ Harap berikan update mengenai perkembangan proyek ini dan jika ada kendala, silakan laporkan segera.
+
+ Terima kasih.
+ [tim_manajemen] + '; + $banks = [ + ['name' => 'Bank A'], + ['name' => 'Bank B'], + ['name' => 'Bank C'], + ['name' => 'Bank D'], + ]; + $templates = [ + ['setting_key' => 'new_order', 'setting_value' => $template_order], + ['setting_key' => 'project_assignment', 'setting_value' => $template_project], + ['setting_key' => 'followup_project', 'setting_value' => $template_followup], + + ['setting_key' => 'app_name', 'setting_value' => 'APP'], + ['setting_key' => 'app_code', 'setting_value' => 'AN'], + ['setting_key' => 'app_description', 'setting_value' => 'Asisten Notaris Online'], + ['setting_key' => 'address', 'setting_value' => 'Jl. Kebon Jeruk, Jakarta Timur'], + ['setting_key' => 'pdf_sample', 'setting_value' => 'path/to/sample.pdf'], + ['setting_key' => 'email', 'setting_value' => 'admin@asistennotaris.com'], + ['setting_key' => 'banks', 'setting_value' => json_encode($banks)] + ]; + + Setting::insert($templates); // Batch insert } } diff --git a/routes/api.php b/routes/api.php index 344a16f..5ce6267 100644 --- a/routes/api.php +++ b/routes/api.php @@ -15,6 +15,8 @@ use App\Http\Controllers\Auth\ProfileController; use App\Http\Controllers\NotificationController; use App\Http\Controllers\PermissionController; +use App\Http\Controllers\BankSettingController; + Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { @@ -31,6 +33,11 @@ Route::get('notifications/unread', [NotificationController::class, 'unread']); Route::get('/permissions', [PermissionController::class, 'index']); Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); + + Route::get('/settings/banks', [BankSettingController::class, 'index']); + Route::post('/settings/banks', [BankSettingController::class, 'store']); + Route::delete('/settings/banks', [BankSettingController::class, 'destroy']); + Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From 96c4379baf0bd2e34badf4d3b54807d8827e21ac Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 18 Feb 2025 13:49:28 +0700 Subject: [PATCH 128/184] fix customer bank meta --- app/Http/Controllers/CustomerController.php | 59 ++++++++++++++++++--- routes/api.php | 4 ++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index c3c09c3..814afc1 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -3,6 +3,7 @@ namespace App\Http\Controllers; use App\Models\Customer; +use App\Models\CustomerMeta; use App\Http\Controllers\Controller; use Illuminate\Http\Request; @@ -25,7 +26,7 @@ public function index(Request $request) 'phone' => 'nullable|string|min:4', ]); - $query = Customer::with('orders'); + $query = Customer::with('orders', 'meta'); if (!empty($validated['name'])) { $query->where('name', 'like', '%' . $validated['name'] . '%'); @@ -45,7 +46,8 @@ public function index(Request $request) 'phone' => $data->phone, 'address' => $data->address, 'order_count' => $data->orders->count(), - 'orders' => $data->orders + 'orders' => $data->orders, + 'meta' => $data->meta ]; }); } else { @@ -57,7 +59,8 @@ public function index(Request $request) 'phone' => $data->phone, 'address' => $data->address, 'order_count' => $data->orders->count(), - 'orders' => $data->orders + 'orders' => $data->orders, + 'meta' => $data->meta ]; }); } @@ -74,16 +77,21 @@ public function store(Request $request) 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20|unique:customers,phone', 'address' => 'required|string', + 'meta' => 'nullable|array', ], [ 'name.required' => 'Nama harus diisi.', 'phone.required' => 'Nomor telepon harus diisi.', 'phone.unique' => 'Nomor telepon sudah ada.', 'address.required' => 'Alamat harus diisi.', + 'meta.array' => 'Meta harus berupa array.', ] ); $customer = Customer::create($validatedData); + if (isset($validatedData['meta'])) { + $customer->meta()->createMany($validatedData['meta']); + } $response = [ 'data' => [ 'id' => $customer->id, @@ -91,7 +99,8 @@ public function store(Request $request) 'phone' => $customer->phone, 'address' => $customer->address, 'order_count' => $customer->orders->count(), - 'orders' => $customer->orders + 'orders' => $customer->orders, + 'meta' => $customer->meta ] ]; return response()->json($response); @@ -117,10 +126,28 @@ public function update(Request $request, Customer $customer) 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20|unique:customers,phone,' . $customer->id, 'address' => 'required|string', + 'meta' => 'nullable|array', + ], + [ + 'name.required' => 'Nama harus diisi.', + 'phone.required' => 'Nomor telepon harus diisi.', + 'phone.unique' => 'Nomor telepon sudah ada.', + 'address.required' => 'Alamat harus diisi.', + 'meta.array' => 'Meta harus berupa array.', ] ); $customer->update($validatedData); - $customer->load('orders'); + if (isset($validatedData['meta'])) { + // tanpa delete meta yang ada, update jika key sama + foreach ($validatedData['meta'] as $metaData) { + $meta = CustomerMeta::updateOrCreate( + ['customer_id' => $customer->id, 'meta_key' => $metaData['meta_key']] + ); + $meta->meta_value = $metaData['meta_value']; + $meta->save(); + } + } + $customer->load('orders', 'meta'); $response = [ 'data' => [ @@ -129,7 +156,8 @@ public function update(Request $request, Customer $customer) 'phone' => $customer->phone, 'address' => $customer->address, 'order_count' => $customer->orders->count(), - 'orders' => $customer->orders + 'orders' => $customer->orders, + 'meta' => $customer->meta ] ]; return response()->json($response); @@ -156,4 +184,23 @@ public function destroy(Customer $customer) return response()->json($customer); } + + public function storeMeta(Request $request, Customer $customer) + { + $validatedData = $request->validate([ + 'meta' => 'required|array', + 'meta.*.meta_key' => 'required|string|max:100', + 'meta.*.meta_value' => 'required|string', + ]); + + foreach ($validatedData['meta'] as $metaData) { + $meta = new CustomerMeta(); + $meta->customer_id = $customer->id; + $meta->meta_key = $metaData['meta_key']; + $meta->meta_value = $metaData['meta_value']; + $meta->save(); + } + + return response()->json(['message' => 'Data meta berhasil disimpan.']); + } } diff --git a/routes/api.php b/routes/api.php index 5ce6267..cc30ffe 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,11 +26,13 @@ Route::post('jobdesk-reminder', [SendNotificationController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('home', [DashboardController::class, 'index']); + Route::get('notifications', [NotificationController::class, 'index']); Route::put('notifications/{id}', [NotificationController::class, 'update']); Route::put('notifications/read/{id}', [NotificationController::class, 'read']); Route::put('notifications/read-all', [NotificationController::class, 'readAll']); Route::get('notifications/unread', [NotificationController::class, 'unread']); + Route::get('/permissions', [PermissionController::class, 'index']); Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); @@ -38,6 +40,8 @@ Route::post('/settings/banks', [BankSettingController::class, 'store']); Route::delete('/settings/banks', [BankSettingController::class, 'destroy']); + Route::post('customers/{customer}/meta', [CustomerController::class, 'storeMeta']); + Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From 7ba43c15513e951b4123fb6899e057c1f1ca7653 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 18 Feb 2025 15:03:21 +0700 Subject: [PATCH 129/184] add filter in customer controller --- app/Http/Controllers/CustomerController.php | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 814afc1..f446466 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -24,6 +24,7 @@ public function index(Request $request) $validated = $request->validate([ 'name' => 'nullable|string|min:3', 'phone' => 'nullable|string|min:4', + 'bank' => 'nullable|string', ]); $query = Customer::with('orders', 'meta'); @@ -36,6 +37,25 @@ public function index(Request $request) $query->where('phone', 'like', '%' . $validated['phone'] . '%'); } + if (!empty($validated['bank'])) { + if ($validated['bank'] === 'Perorangan') { + $query->where(function ($q) { + $q->whereHas('meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', 'Perorangan'); + })->orWhereDoesntHave('meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank'); + }); + }); + } else { + $query->whereHas('meta', function ($subQuery) use ($validated) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', 'like', '%' . $validated['bank'] . '%'); + }); + } + } + + $query->orderBy('created_at', 'desc'); if ($paginate === 'false') { From cf021907df9902413b732dc04c0c2ccd76c41551 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 19 Feb 2025 11:52:55 +0700 Subject: [PATCH 130/184] add filter bank in order controller --- app/Http/Controllers/CustomerController.php | 1 - app/Http/Controllers/OrderController.php | 23 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index f446466..c3f381d 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -55,7 +55,6 @@ public function index(Request $request) } } - $query->orderBy('created_at', 'desc'); if ($paginate === 'false') { diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index ef3cb75..8ee8ff2 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -29,16 +29,35 @@ public function index(Request $request) $paginate = $request->query('paginate'); $name = $request->query('name'); $productQuery = $request->query('product'); + $bank = $request->query('bank'); $status = $request->query('status'); $status = isset($status) ? $status : null; $user = $request->user(); - $query = Order::with('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); + $query = Order::with('customer', 'customer.meta', 'jobdesks', 'product', 'product.metaProducts.meta'); if (isset($customerId) && $customerId !== 'undefined') { $query->where('customer_id', $customerId); } + if (!empty($bank)) { + if ($bank === 'Perorangan') { + $query->where(function ($q) { + $q->whereHas('customer.meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', 'Perorangan'); + })->orWhereDoesntHave('customer.meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank'); + }); + }); + } else { + $query->whereHas('customer.meta', function ($subQuery) use ($bank) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', 'like', '%' . $bank . '%'); + }); + } + } + if ($name || $productQuery) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); @@ -89,6 +108,7 @@ public function index(Request $request) 'name' => $data->customer->name, 'phone' => $data->customer->phone, 'address' => $data->customer->address, + 'meta' => $data->customer->meta ], 'jobdesks' => $data->jobdesks, 'product' => [ @@ -122,6 +142,7 @@ public function index(Request $request) 'name' => $data->customer->name, 'phone' => $data->customer->phone, 'address' => $data->customer->address, + 'meta' => $data->customer->meta ] : null, 'jobdesks' => $data->jobdesks, 'product' => $data->product ? [ From d80288bdc70d492940b39b8438541ca2dcfd5fa5 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 19 Feb 2025 14:21:21 +0700 Subject: [PATCH 131/184] ganti kondisi where menjadi sama persis --- app/Http/Controllers/OrderController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 8ee8ff2..931a729 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -53,7 +53,7 @@ public function index(Request $request) } else { $query->whereHas('customer.meta', function ($subQuery) use ($bank) { $subQuery->where('meta_key', 'bank') - ->where('meta_value', 'like', '%' . $bank . '%'); + ->where('meta_value', '=', $bank); }); } } From 4bb7fc32052895f803153f6668ddf20e3b4693bf Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 20 Feb 2025 14:15:21 +0700 Subject: [PATCH 132/184] fix order query --- app/Http/Controllers/OrderController.php | 42 +++++++++++++----------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 931a729..d85d0d8 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -40,31 +40,19 @@ public function index(Request $request) $query->where('customer_id', $customerId); } - if (!empty($bank)) { - if ($bank === 'Perorangan') { - $query->where(function ($q) { - $q->whereHas('customer.meta', function ($subQuery) { - $subQuery->where('meta_key', 'bank') - ->where('meta_value', 'Perorangan'); - })->orWhereDoesntHave('customer.meta', function ($subQuery) { - $subQuery->where('meta_key', 'bank'); - }); - }); - } else { - $query->whereHas('customer.meta', function ($subQuery) use ($bank) { - $subQuery->where('meta_key', 'bank') - ->where('meta_value', '=', $bank); - }); - } - } - - if ($name || $productQuery) { + if ($name || $productQuery || $bank) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); }); $query->whereHas('product', function ($query) use ($productQuery) { $query->where('name', 'like', '%' . $productQuery . '%'); }); + if ($bank) { + $query->whereHas('customer.meta', function ($subQuery) use ($bank) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', '=', $bank); + }); + } } else { if ($status) { $query->whereDoesntHave('jobdesks', function ($query) use ($status) { @@ -77,6 +65,22 @@ public function index(Request $request) $query->whereNull('lampiran'); } $query->whereHas('jobdesks'); + } else if ($bank) { + if ($bank === 'Perorangan') { + $query->where(function ($q) { + $q->whereHas('customer.meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', 'Perorangan'); + })->orWhereDoesntHave('customer.meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank'); + }); + }); + } else { + $query->whereHas('customer.meta', function ($subQuery) use ($bank) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', '=', $bank); + }); + } } else if (!($customerId || $name)) { $query->whereHas('jobdesks', function ($query) { $query->where('status', '!=', 'Selesai'); From bd9e957db0a95b288f4dc0e3512d1e38d88d6b5b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 21 Feb 2025 14:58:43 +0700 Subject: [PATCH 133/184] add setting image support --- .../SettingBackgroundController.php | 76 +++++++++++++++++++ ...ntroller.php => SettingBankController.php} | 2 +- routes/api.php | 17 +++-- 3 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 app/Http/Controllers/SettingBackgroundController.php rename app/Http/Controllers/{BankSettingController.php => SettingBankController.php} (96%) diff --git a/app/Http/Controllers/SettingBackgroundController.php b/app/Http/Controllers/SettingBackgroundController.php new file mode 100644 index 0000000..1b34904 --- /dev/null +++ b/app/Http/Controllers/SettingBackgroundController.php @@ -0,0 +1,76 @@ +first(); + $background = $setting ? json_decode($setting->setting_value, true) : []; + return response()->json([ + 'color' => $background['color'] ?? null, + 'image' => $background['image'] ?? null, + ]); + } + + /** + * Store or update the background settings. + */ + public function store(Request $request) + { + $validatedData = $request->validate([ + 'color' => 'nullable|string|max:7', // Format hex warna (#FFFFFF) + 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // Maksimal 2MB + ]); + + $background = []; + + // Simpan warna jika ada + if ($request->has('color')) { + $background['color'] = $request->input('color'); + } + + //hapus gambar lama dari storage + if ($request->hasFile('image')) { + $oldImage = Setting::where('setting_key', 'background')->first(); + if ($oldImage) { + $oldImagePath = $oldImage->setting_value; + if (isset($oldImagePath['image'])) { + $oldImage = $oldImagePath['image']; + Storage::disk('public')->delete($oldImage); + } + } + } + + // Simpan gambar jika ada + if ($request->hasFile('image')) { + $imagePath = $request->file('image')->store('backgrounds', 'public'); + $background['image'] = asset('storage/' . $imagePath); + } + + // Simpan ke database + Setting::updateOrCreate( + ['setting_key' => 'background'], + ['setting_value' => json_encode($background)] + ); + + return response()->json(['message' => 'Pengaturan latar belakang berhasil disimpan.']); + } + + /** + * Remove the background settings. + */ + public function destroy() + { + Setting::where('setting_key', 'background')->delete(); + return response()->json(['message' => 'Pengaturan latar belakang berhasil dihapus.']); + } +} diff --git a/app/Http/Controllers/BankSettingController.php b/app/Http/Controllers/SettingBankController.php similarity index 96% rename from app/Http/Controllers/BankSettingController.php rename to app/Http/Controllers/SettingBankController.php index 7f39cb6..9ef5eda 100644 --- a/app/Http/Controllers/BankSettingController.php +++ b/app/Http/Controllers/SettingBankController.php @@ -5,7 +5,7 @@ use App\Models\Setting; use Illuminate\Http\Request; -class BankSettingController extends Controller +class SettingBankController extends Controller { /** * Get the list of banks from settings. diff --git a/routes/api.php b/routes/api.php index cc30ffe..e44d94f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -15,8 +15,8 @@ use App\Http\Controllers\Auth\ProfileController; use App\Http\Controllers\NotificationController; use App\Http\Controllers\PermissionController; -use App\Http\Controllers\BankSettingController; - +use App\Http\Controllers\SettingBankController; +use App\Http\Controllers\SettingBackgroundController; Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { @@ -36,9 +36,16 @@ Route::get('/permissions', [PermissionController::class, 'index']); Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); - Route::get('/settings/banks', [BankSettingController::class, 'index']); - Route::post('/settings/banks', [BankSettingController::class, 'store']); - Route::delete('/settings/banks', [BankSettingController::class, 'destroy']); + + Route::prefix('settings')->group(function () { + Route::get('/background', [SettingBackgroundController::class, 'index']); + Route::post('/background', [SettingBackgroundController::class, 'store']); + Route::delete('/background', [SettingBackgroundController::class, 'destroy']); + + Route::get('/banks', [SettingBankController::class, 'index']); + Route::post('/banks', [SettingBankController::class, 'store']); + Route::delete('/banks', [SettingBankController::class, 'destroy']); + }); Route::post('customers/{customer}/meta', [CustomerController::class, 'storeMeta']); From 2d4f268581b48a4c5b9637fe22dd7e35a8f3f186 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 21 Feb 2025 21:04:01 +0700 Subject: [PATCH 134/184] add background controller --- .../Controllers/SettingBackgroundController.php | 13 ++++++++----- routes/api.php | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/SettingBackgroundController.php b/app/Http/Controllers/SettingBackgroundController.php index 1b34904..365353b 100644 --- a/app/Http/Controllers/SettingBackgroundController.php +++ b/app/Http/Controllers/SettingBackgroundController.php @@ -6,7 +6,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; -class BackgroundSettingController extends Controller +class SettingBackgroundController extends Controller { /** * Get the background settings. @@ -39,7 +39,7 @@ public function store(Request $request) } //hapus gambar lama dari storage - if ($request->hasFile('image')) { + if ($request->hasFile('image') && $request->file('image')->isValid()) { $oldImage = Setting::where('setting_key', 'background')->first(); if ($oldImage) { $oldImagePath = $oldImage->setting_value; @@ -48,14 +48,17 @@ public function store(Request $request) Storage::disk('public')->delete($oldImage); } } - } - // Simpan gambar jika ada - if ($request->hasFile('image')) { $imagePath = $request->file('image')->store('backgrounds', 'public'); $background['image'] = asset('storage/' . $imagePath); } + // jika tidak ada gambar baru, gunakan gambar lama + if (!isset($background['image'])) { + $oldImage = Setting::where('setting_key', 'background')->first(); + $background['image'] = $oldImage ? json_decode($oldImage->setting_value, true)['image'] : null; + } + // Simpan ke database Setting::updateOrCreate( ['setting_key' => 'background'], diff --git a/routes/api.php b/routes/api.php index e44d94f..bb638ae 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,6 +18,8 @@ use App\Http\Controllers\SettingBankController; use App\Http\Controllers\SettingBackgroundController; +Route::get('/settings/background', [SettingBackgroundController::class, 'index']); + Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { return $request->user(); @@ -36,9 +38,7 @@ Route::get('/permissions', [PermissionController::class, 'index']); Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); - Route::prefix('settings')->group(function () { - Route::get('/background', [SettingBackgroundController::class, 'index']); Route::post('/background', [SettingBackgroundController::class, 'store']); Route::delete('/background', [SettingBackgroundController::class, 'destroy']); From 36022fec604727e633ea799faeddb59c3cb5d918 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 25 Feb 2025 09:23:43 +0700 Subject: [PATCH 135/184] add icon setting --- .../Controllers/SettingFaviconController.php | 76 +++++++++++++++++++ routes/api.php | 5 ++ 2 files changed, 81 insertions(+) create mode 100644 app/Http/Controllers/SettingFaviconController.php diff --git a/app/Http/Controllers/SettingFaviconController.php b/app/Http/Controllers/SettingFaviconController.php new file mode 100644 index 0000000..07e02b1 --- /dev/null +++ b/app/Http/Controllers/SettingFaviconController.php @@ -0,0 +1,76 @@ +first(); + $favicon = $setting ? json_decode($setting->setting_value, true) : []; + + return response()->json([ + 'favicon' => $favicon['favicon'] ?? null, + ]); + } + + /** + * Store or update the favicon settings. + */ + public function store(Request $request) + { + $validatedData = $request->validate([ + 'favicon' => 'nullable|image|mimes:png,ico|max:1024', // Maksimal 1MB, hanya PNG atau ICO + ]); + + $favicon = []; + + // Ambil data lama + $setting = Setting::where('setting_key', 'favicon')->first(); + $oldFavicon = $setting ? json_decode($setting->setting_value, true) : []; + + // Hapus favicon lama jika ada favicon baru yang diunggah + if ($request->hasFile('favicon') && $request->file('favicon')->isValid()) { + if (!empty($oldFavicon['favicon'])) { + Storage::disk('public')->delete(str_replace(asset('storage/'), '', $oldFavicon['favicon'])); + } + + $faviconPath = $request->file('favicon')->store('favicons', 'public'); + $favicon['favicon'] = asset('storage/' . $faviconPath); + } else { + $favicon['favicon'] = $oldFavicon['favicon'] ?? null; + } + + // Simpan ke database + Setting::updateOrCreate( + ['setting_key' => 'favicon'], + ['setting_value' => json_encode($favicon)] + ); + + return response()->json(['message' => 'Favicon berhasil disimpan.']); + } + + /** + * Remove the favicon settings. + */ + public function destroy() + { + $setting = Setting::where('setting_key', 'favicon')->first(); + if ($setting) { + $favicon = json_decode($setting->setting_value, true); + if (!empty($favicon['favicon'])) { + Storage::disk('public')->delete(str_replace(asset('storage/'), '', $favicon['favicon'])); + } + $setting->delete(); + } + + return response()->json(['message' => 'Favicon berhasil dihapus.']); + } +} diff --git a/routes/api.php b/routes/api.php index bb638ae..1e8ecdd 100644 --- a/routes/api.php +++ b/routes/api.php @@ -17,8 +17,10 @@ use App\Http\Controllers\PermissionController; use App\Http\Controllers\SettingBankController; use App\Http\Controllers\SettingBackgroundController; +use App\Http\Controllers\SettingFaviconController; Route::get('/settings/background', [SettingBackgroundController::class, 'index']); +Route::get('/settings/favicon', [SettingFaviconController::class, 'index']); Route::middleware(['auth:sanctum'])->group(function () { Route::get('profile', function (Request $request) { @@ -42,6 +44,9 @@ Route::post('/background', [SettingBackgroundController::class, 'store']); Route::delete('/background', [SettingBackgroundController::class, 'destroy']); + Route::post('/favicon', [SettingFaviconController::class, 'store']); + Route::delete('/favicon', [SettingFaviconController::class, 'destroy']); + Route::get('/banks', [SettingBankController::class, 'index']); Route::post('/banks', [SettingBankController::class, 'store']); Route::delete('/banks', [SettingBankController::class, 'destroy']); From 3be89da55555f94721b0f5500bd51a6444867574 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 25 Feb 2025 14:35:58 +0700 Subject: [PATCH 136/184] perapian route api --- routes/api.php | 78 +++++++++++++++++++++++++++++--------------------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/routes/api.php b/routes/api.php index 1e8ecdd..e67f588 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,58 +2,72 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; -use App\Http\Controllers\KaryawanController; -use App\Http\Controllers\OrderController; -use App\Http\Controllers\JobdeskController; -use App\Http\Controllers\CustomerController; -use App\Http\Controllers\DashboardController; -use App\Http\Controllers\SettingController; -use App\Http\Controllers\UserController; -use App\Http\Controllers\ProductController; -use App\Http\Controllers\MetaController; -use App\Http\Controllers\SendNotificationController; -use App\Http\Controllers\Auth\ProfileController; -use App\Http\Controllers\NotificationController; -use App\Http\Controllers\PermissionController; -use App\Http\Controllers\SettingBankController; -use App\Http\Controllers\SettingBackgroundController; -use App\Http\Controllers\SettingFaviconController; +use App\Http\Controllers\{ + KaryawanController, + OrderController, + JobdeskController, + CustomerController, + DashboardController, + SettingController, + UserController, + ProductController, + MetaController, + SendNotificationController, + NotificationController, + PermissionController, + SettingBankController, + SettingBackgroundController, + SettingFaviconController, + Auth\ProfileController +}; +// Routes tanpa middleware Route::get('/settings/background', [SettingBackgroundController::class, 'index']); Route::get('/settings/favicon', [SettingFaviconController::class, 'index']); +// Routes dengan middleware 'auth:sanctum' Route::middleware(['auth:sanctum'])->group(function () { - Route::get('profile', function (Request $request) { - return $request->user(); - }); + Route::get('profile', fn(Request $request) => $request->user()); Route::get('user', [UserController::class, 'index']); - Route::post('jobdesk-reminder', [SendNotificationController::class, 'sendJobdeskReminder']); Route::put('profile', [ProfileController::class, 'update']); Route::get('home', [DashboardController::class, 'index']); + Route::post('jobdesk-reminder', [SendNotificationController::class, 'sendJobdeskReminder']); - Route::get('notifications', [NotificationController::class, 'index']); - Route::put('notifications/{id}', [NotificationController::class, 'update']); - Route::put('notifications/read/{id}', [NotificationController::class, 'read']); - Route::put('notifications/read-all', [NotificationController::class, 'readAll']); - Route::get('notifications/unread', [NotificationController::class, 'unread']); + // Notifications + Route::controller(NotificationController::class)->group(function () { + Route::get('notifications', 'index'); + Route::put('notifications/{id}', 'update'); + Route::put('notifications/read/{id}', 'read'); + Route::put('notifications/read-all', 'readAll'); + Route::get('notifications/unread', 'unread'); + }); + // Permissions Route::get('/permissions', [PermissionController::class, 'index']); Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); + // Settings Route::prefix('settings')->group(function () { - Route::post('/background', [SettingBackgroundController::class, 'store']); - Route::delete('/background', [SettingBackgroundController::class, 'destroy']); + Route::controller(SettingBackgroundController::class)->group(function () { + Route::post('/background', 'store'); + Route::delete('/background', 'destroy'); + }); - Route::post('/favicon', [SettingFaviconController::class, 'store']); - Route::delete('/favicon', [SettingFaviconController::class, 'destroy']); + Route::controller(SettingFaviconController::class)->group(function () { + Route::post('/favicon', 'store'); + Route::delete('/favicon', 'destroy'); + }); - Route::get('/banks', [SettingBankController::class, 'index']); - Route::post('/banks', [SettingBankController::class, 'store']); - Route::delete('/banks', [SettingBankController::class, 'destroy']); + Route::controller(SettingBankController::class)->group(function () { + Route::get('/banks', 'index'); + Route::post('/banks', 'store'); + Route::delete('/banks', 'destroy'); + }); }); Route::post('customers/{customer}/meta', [CustomerController::class, 'storeMeta']); + // API Resources Route::apiResources([ 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, From 0d892f99219d3e68c9a443cb6a9e65997d3b76cf Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 27 Feb 2025 15:29:25 +0700 Subject: [PATCH 137/184] Update controller setting background --- app/Http/Controllers/SettingBackgroundController.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/SettingBackgroundController.php b/app/Http/Controllers/SettingBackgroundController.php index 365353b..ef954a2 100644 --- a/app/Http/Controllers/SettingBackgroundController.php +++ b/app/Http/Controllers/SettingBackgroundController.php @@ -18,6 +18,7 @@ public function index() return response()->json([ 'color' => $background['color'] ?? null, 'image' => $background['image'] ?? null, + 'style' => $background['style'] ?? null ]); } @@ -29,6 +30,7 @@ public function store(Request $request) $validatedData = $request->validate([ 'color' => 'nullable|string|max:7', // Format hex warna (#FFFFFF) 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // Maksimal 2MB + 'style' => 'nullable|string', ]); $background = []; @@ -38,6 +40,11 @@ public function store(Request $request) $background['color'] = $request->input('color'); } + // Simpan style jika ada + if ($request->has('style')) { + $background['style'] = $request->input('style'); + } + //hapus gambar lama dari storage if ($request->hasFile('image') && $request->file('image')->isValid()) { $oldImage = Setting::where('setting_key', 'background')->first(); @@ -62,7 +69,7 @@ public function store(Request $request) // Simpan ke database Setting::updateOrCreate( ['setting_key' => 'background'], - ['setting_value' => json_encode($background)] + ['setting_value' => json_encode($background)], ); return response()->json(['message' => 'Pengaturan latar belakang berhasil disimpan.']); From 671734b0ab717a95c2109a6a0d78131d9423767d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 28 Feb 2025 08:17:09 +0700 Subject: [PATCH 138/184] ganti penamaan controller --- ...gBackgroundController.php => SettingLoginController.php} | 2 +- routes/api.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename app/Http/Controllers/{SettingBackgroundController.php => SettingLoginController.php} (97%) diff --git a/app/Http/Controllers/SettingBackgroundController.php b/app/Http/Controllers/SettingLoginController.php similarity index 97% rename from app/Http/Controllers/SettingBackgroundController.php rename to app/Http/Controllers/SettingLoginController.php index ef954a2..5484815 100644 --- a/app/Http/Controllers/SettingBackgroundController.php +++ b/app/Http/Controllers/SettingLoginController.php @@ -6,7 +6,7 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; -class SettingBackgroundController extends Controller +class SettingLoginController extends Controller { /** * Get the background settings. diff --git a/routes/api.php b/routes/api.php index e67f588..6c9a038 100644 --- a/routes/api.php +++ b/routes/api.php @@ -16,13 +16,13 @@ NotificationController, PermissionController, SettingBankController, - SettingBackgroundController, + SettingLoginController, SettingFaviconController, Auth\ProfileController }; // Routes tanpa middleware -Route::get('/settings/background', [SettingBackgroundController::class, 'index']); +Route::get('/settings/background', [SettingLoginController::class, 'index']); Route::get('/settings/favicon', [SettingFaviconController::class, 'index']); // Routes dengan middleware 'auth:sanctum' @@ -48,7 +48,7 @@ // Settings Route::prefix('settings')->group(function () { - Route::controller(SettingBackgroundController::class)->group(function () { + Route::controller(SettingLoginController::class)->group(function () { Route::post('/background', 'store'); Route::delete('/background', 'destroy'); }); From ef431fb5f138b20774fcbcb8ad1e352f8fd25fd5 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 28 Feb 2025 15:31:26 +0700 Subject: [PATCH 139/184] add crud post --- app/Http/Controllers/CategoryController.php | 71 +++++++++++++++++++ app/Http/Controllers/PostController.php | 58 +++++++++++++++ app/Models/Category.php | 18 +++++ app/Models/Post.php | 23 ++++++ ...5_02_28_092405_create_categories_table.php | 22 ++++++ .../2025_02_28_092410_create_posts_table.php | 26 +++++++ routes/api.php | 4 ++ 7 files changed, 222 insertions(+) create mode 100644 app/Http/Controllers/CategoryController.php create mode 100644 app/Http/Controllers/PostController.php create mode 100644 app/Models/Category.php create mode 100644 app/Models/Post.php create mode 100644 database/migrations/2025_02_28_092405_create_categories_table.php create mode 100644 database/migrations/2025_02_28_092410_create_posts_table.php diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php new file mode 100644 index 0000000..b3e810f --- /dev/null +++ b/app/Http/Controllers/CategoryController.php @@ -0,0 +1,71 @@ +json(Category::all()); + } + + /** + * Store a newly created category in storage. + */ + public function store(Request $request) + { + $request->validate([ + 'name' => 'required|string|max:255|unique:categories,name', + ]); + + $slug = str_replace(' ', '-', strtolower($request->name)); + $category = Category::create([ + 'name' => $request->name, + 'slug' => $slug + ]); + + return response()->json($category, Response::HTTP_CREATED); + } + + /** + * Display the specified category. + */ + public function show(Category $category) + { + return response()->json($category); + } + + /** + * Update the specified category in storage. + */ + public function update(Request $request, Category $category) + { + $request->validate([ + 'name' => 'required|string|max:255|unique:categories,name,' . $category->id, + ]); + $slug = str_replace(' ', '-', strtolower($request->name)); + $category->update([ + 'name' => $request->name, + 'slug' => $slug + ]); + + return response()->json($category); + } + + /** + * Remove the specified category from storage. + */ + public function destroy(Category $category) + { + $category->delete(); + + return response()->json(null, Response::HTTP_NO_CONTENT); + } +} diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php new file mode 100644 index 0000000..981f3cf --- /dev/null +++ b/app/Http/Controllers/PostController.php @@ -0,0 +1,58 @@ +paginate(10); + return response()->json($posts); + } + + public function show(Post $post) + { + return response()->json($post); + } + + public function store(Request $request) + { + $user_id = $request->user()->id; + $request->validate([ + 'title' => 'required|string|max:255', + 'content' => 'required', + 'category_id' => 'required|exists:categories,id', + 'featured_image' => 'nullable|string', + ]); + $slug = str_replace(' ', '-', strtolower($request->title)); + $request->merge(['slug' => $slug]); + $request->merge(['user_id' => $user_id]); + $post = Post::create($request->all()); + return response()->json($post, 201); + } + + public function update(Request $request, Post $post) + { + $user_id = $request->user()->id; + $request->validate([ + 'title' => 'sometimes|string|max:255', + 'content' => 'sometimes', + 'category_id' => 'sometimes|exists:categories,id', + 'featured_image' => 'nullable|string', + ]); + $slug = str_replace(' ', '-', strtolower($request->title)); + $request->merge(['slug' => $slug]); + $request->merge(['user_id' => $user_id]); + $post->update($request->all()); + return response()->json($post); + } + + public function destroy(Post $post) + { + $post->delete(); + return response()->json(['message' => 'Post deleted successfully']); + } +} diff --git a/app/Models/Category.php b/app/Models/Category.php new file mode 100644 index 0000000..da98535 --- /dev/null +++ b/app/Models/Category.php @@ -0,0 +1,18 @@ +hasMany(Post::class); + } +} diff --git a/app/Models/Post.php b/app/Models/Post.php new file mode 100644 index 0000000..8509a37 --- /dev/null +++ b/app/Models/Post.php @@ -0,0 +1,23 @@ +belongsTo(User::class); + } + + public function category() + { + return $this->belongsTo(Category::class); + } +} diff --git a/database/migrations/2025_02_28_092405_create_categories_table.php b/database/migrations/2025_02_28_092405_create_categories_table.php new file mode 100644 index 0000000..f92547d --- /dev/null +++ b/database/migrations/2025_02_28_092405_create_categories_table.php @@ -0,0 +1,22 @@ +id(); + $table->string('name')->unique(); + $table->string('slug')->unique(); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('categories'); + } +}; diff --git a/database/migrations/2025_02_28_092410_create_posts_table.php b/database/migrations/2025_02_28_092410_create_posts_table.php new file mode 100644 index 0000000..4cc1642 --- /dev/null +++ b/database/migrations/2025_02_28_092410_create_posts_table.php @@ -0,0 +1,26 @@ +id(); + $table->string('title'); + $table->text('content'); + $table->string('slug')->unique(); + $table->foreignId('user_id')->constrained()->onDelete('cascade'); + $table->string('featured_image')->nullable(); + $table->foreignId('category_id')->constrained('categories')->onDelete('cascade'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('posts'); + } +}; diff --git a/routes/api.php b/routes/api.php index 6c9a038..c492c78 100644 --- a/routes/api.php +++ b/routes/api.php @@ -18,6 +18,8 @@ SettingBankController, SettingLoginController, SettingFaviconController, + PostController, + CategoryController, Auth\ProfileController }; @@ -69,6 +71,8 @@ // API Resources Route::apiResources([ + 'posts' => PostController::class, + 'categories' => CategoryController::class, 'karyawans' => KaryawanController::class, 'orders' => OrderController::class, 'jobdesks' => JobdeskController::class, From 7e0ff50f8658c0d68578fe8b7208e360497c056c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 1 Mar 2025 15:00:54 +0700 Subject: [PATCH 140/184] fix image post --- app/Http/Controllers/PostController.php | 111 +++++++++++++++++++----- 1 file changed, 88 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php index 981f3cf..6268fa2 100644 --- a/app/Http/Controllers/PostController.php +++ b/app/Http/Controllers/PostController.php @@ -2,8 +2,9 @@ namespace App\Http\Controllers; -use App\Models\Post; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Storage; +use App\Models\Post; class PostController extends Controller { @@ -20,39 +21,103 @@ public function show(Post $post) public function store(Request $request) { - $user_id = $request->user()->id; - $request->validate([ - 'title' => 'required|string|max:255', - 'content' => 'required', - 'category_id' => 'required|exists:categories,id', - 'featured_image' => 'nullable|string', - ]); - $slug = str_replace(' ', '-', strtolower($request->title)); - $request->merge(['slug' => $slug]); - $request->merge(['user_id' => $user_id]); - $post = Post::create($request->all()); + // Validasi input + $validated = $request->validate( + [ + 'title' => 'required|string|max:255', + 'content' => 'required|string', + 'category_id' => 'required|exists:categories,id', + 'featured_image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // Validasi file gambar + ], + [ + 'title.required' => 'Judul harus diisi.', + 'content.required' => 'Isi konten harus diisi.', + 'category_id.required' => 'Kategori harus dipilih.', + 'category_id.exists' => 'Kategori tidak ditemukan.', + 'featured_image.image' => 'File harus berupa gambar.', + 'featured_image.mimes' => 'Format file harus JPEG, PNG, JPG, atau GIF.', + 'featured_image.max' => 'Ukuran file maksimal 2MB.', + ] + ); + + // Handle Featured Image + if ($request->hasFile('featured_image')) { + $validated['featured_image'] = $request->file('featured_image')->store('images', 'public'); + $validated['featured_image'] = asset('storage/' . $validated['featured_image']); + } else { + unset($validated['featured_image']); // Jika tidak ada file, hapus key ini + } + + // Tambahkan slug dan user_id + $slug = str_replace(' ', '-', strtolower($validated['title'])); + $validated['slug'] = $slug; + $validated['user_id'] = $request->user()->id; + + // Simpan data ke database + $post = Post::create($validated); + + // Return respons JSON return response()->json($post, 201); } public function update(Request $request, Post $post) { - $user_id = $request->user()->id; - $request->validate([ - 'title' => 'sometimes|string|max:255', - 'content' => 'sometimes', - 'category_id' => 'sometimes|exists:categories,id', - 'featured_image' => 'nullable|string', - ]); - $slug = str_replace(' ', '-', strtolower($request->title)); - $request->merge(['slug' => $slug]); - $request->merge(['user_id' => $user_id]); - $post->update($request->all()); + // Validasi input + $validated = $request->validate( + [ + 'title' => 'sometimes|string|max:255', + 'content' => 'sometimes|string', + 'category_id' => 'sometimes|exists:categories,id', + 'featured_image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // Validasi file gambar + ], + [ + 'title.required' => 'Judul harus diisi.', + 'content.required' => 'Isi konten harus diisi.', + 'category_id.required' => 'Kategori harus dipilih.', + 'category_id.exists' => 'Kategori tidak ditemukan.', + 'featured_image.image' => 'File harus berupa gambar.', + 'featured_image.mimes' => 'Format file harus JPEG, PNG, JPG, atau GIF.', + 'featured_image.max' => 'Ukuran file maksimal 2MB.', + ] + ); + + // Handle Featured Image + if ($request->hasFile('featured_image')) { + // Hapus gambar lama jika ada + if ($post->featured_image) { + Storage::disk('public')->delete($post->featured_image); + } + // Simpan gambar baru + $validated['featured_image'] = $request->file('featured_image')->store('images', 'public'); + $validated['featured_image'] = asset('storage/' . $validated['featured_image']); + } elseif (is_string($request->featured_image)) { + unset($validated['featured_image']); // Jika featured_image adalah string, abaikan + } + + // Update slug jika title berubah + if (isset($validated['title'])) { + $slug = str_replace(' ', '-', strtolower($validated['title'])); + $validated['slug'] = $slug; + } + + // Update data post + $post->update($validated); + + // Return respons JSON return response()->json($post); } public function destroy(Post $post) { + // Hapus gambar dari storage jika ada + if ($post->featured_image) { + Storage::disk('public')->delete($post->featured_image); + } + + // Hapus data post $post->delete(); + + // Return respons JSON return response()->json(['message' => 'Post deleted successfully']); } } From a4d581e39bc0ba37c05ab558aa9f654b8091e642 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 3 Mar 2025 14:15:45 +0700 Subject: [PATCH 141/184] fix source gambar --- app/Http/Controllers/Auth/ProfileController.php | 4 ++-- app/Http/Controllers/KaryawanController.php | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index 494c70e..c79bfb8 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -28,12 +28,12 @@ public function update(ProfileUpdateRequest $request) // Menangani avatar if ($request->hasFile('avatar')) { - $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); - // Hapus avatar lama jika ada if ($user->avatar) { Storage::disk('public')->delete($user->avatar); } + $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); + $validated['avatar'] = asset('storage/' . $validated['avatar']); } else { // Jika tidak ada file avatar, gunakan avatar yang ada $validated['avatar'] = $user->avatar; diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index d48e0e9..442608b 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -102,10 +102,11 @@ public function update(Request $request, $id) // Handle Avatar if ($request->hasFile('avatar')) { - $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); if ($user->avatar) { Storage::disk('public')->delete($user->avatar); } + $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); + $validated['avatar'] = asset('storage/' . $validated['avatar']); } else { unset($validated['avatar']); } @@ -152,6 +153,7 @@ public function store(Request $request) unset($validated['avatar']); } elseif ($request->hasFile('avatar')) { $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); + $validated['avatar'] = asset('storage/' . $validated['avatar']); } $validated['password'] = bcrypt($validated['password']); From 2905624d1650888f8de84b8191635ad9dec31e56 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 4 Mar 2025 08:42:38 +0700 Subject: [PATCH 142/184] max lampiran 15 MB --- app/Http/Controllers/OrderController.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index d85d0d8..719df00 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -176,7 +176,11 @@ public function update(Request $request, Order $order) // Jika ada lampiran, hanya validasi lampiran if ($request->hasFile('lampiran')) { $request->validate([ - 'lampiran' => 'required|mimes:pdf', + 'lampiran' => 'required|mimes:pdf|max:15000', + ], [ + 'lampiran.required' => 'Lampiran harus diisi.', + 'lampiran.mimes' => 'Lampiran harus berupa file PDF.', + 'lampiran.max' => 'Lampiran tidak boleh lebih besar dari 15MB.', ]); $filePath = $request->file('lampiran')->store('lampiran', 'public'); From 3a11cf63c55ce895591159620ac6b035a3abe479 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 10 Mar 2025 13:57:47 +0700 Subject: [PATCH 143/184] add categori to post controller --- app/Http/Controllers/PostController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/PostController.php b/app/Http/Controllers/PostController.php index 6268fa2..4cd25f8 100644 --- a/app/Http/Controllers/PostController.php +++ b/app/Http/Controllers/PostController.php @@ -11,6 +11,7 @@ class PostController extends Controller public function index() { $posts = Post::latest()->paginate(10); + $posts->load('category'); return response()->json($posts); } From e067952882c0f9f18f09730cb83e777bde55725c Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 11 Mar 2025 10:44:40 +0700 Subject: [PATCH 144/184] add list jobdesk in karyawan controller --- app/Http/Controllers/KaryawanController.php | 3 +- bun.lock | 117 ++++++++++++++++++++ 2 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 bun.lock diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 442608b..759eb90 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -7,7 +7,6 @@ use Illuminate\Support\Facades\Storage; use App\Models\User; use App\Models\Jobdesk; -use App\Notifications\PendingJobdesk; class KaryawanController extends Controller @@ -80,6 +79,8 @@ public function index(Request $request) public function show($id) { $user = User::find($id); + // load jobdesk + $user->load('jobdesk'); return response()->json($user); } diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..fc15f14 --- /dev/null +++ b/bun.lock @@ -0,0 +1,117 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "larapi", + "dependencies": { + "archiver": "^5.3.1", + "fs": "0.0.1-security", + }, + }, + }, + "packages": { + "archiver": ["archiver@5.3.2", "", { "dependencies": { "archiver-utils": "^2.1.0", "async": "^3.2.4", "buffer-crc32": "^0.2.1", "readable-stream": "^3.6.0", "readdir-glob": "^1.1.2", "tar-stream": "^2.2.0", "zip-stream": "^4.1.0" } }, "sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw=="], + + "archiver-utils": ["archiver-utils@2.1.0", "", { "dependencies": { "glob": "^7.1.4", "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", "lodash.defaults": "^4.2.0", "lodash.difference": "^4.5.0", "lodash.flatten": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^2.0.0" } }, "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw=="], + + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + + "brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "buffer-crc32": ["buffer-crc32@0.2.13", "", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + + "compress-commons": ["compress-commons@4.1.2", "", { "dependencies": { "buffer-crc32": "^0.2.13", "crc32-stream": "^4.0.2", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" } }, "sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "core-util-is": ["core-util-is@1.0.3", "", {}, "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="], + + "crc-32": ["crc-32@1.2.2", "", { "bin": { "crc32": "bin/crc32.njs" } }, "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ=="], + + "crc32-stream": ["crc32-stream@4.0.3", "", { "dependencies": { "crc-32": "^1.2.0", "readable-stream": "^3.4.0" } }, "sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw=="], + + "end-of-stream": ["end-of-stream@1.4.4", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q=="], + + "fs": ["fs@0.0.1-security", "", {}, "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="], + + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + + "fs.realpath": ["fs.realpath@1.0.0", "", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "isarray": ["isarray@1.0.0", "", {}, "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="], + + "lazystream": ["lazystream@1.0.1", "", { "dependencies": { "readable-stream": "^2.0.5" } }, "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw=="], + + "lodash.defaults": ["lodash.defaults@4.2.0", "", {}, "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="], + + "lodash.difference": ["lodash.difference@4.5.0", "", {}, "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA=="], + + "lodash.flatten": ["lodash.flatten@4.4.0", "", {}, "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g=="], + + "lodash.isplainobject": ["lodash.isplainobject@4.0.6", "", {}, "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA=="], + + "lodash.union": ["lodash.union@4.6.0", "", {}, "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw=="], + + "minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + + "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "process-nextick-args": ["process-nextick-args@2.0.1", "", {}, "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="], + + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "readdir-glob": ["readdir-glob@1.1.3", "", { "dependencies": { "minimatch": "^5.1.0" } }, "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA=="], + + "safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], + + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "zip-stream": ["zip-stream@4.1.1", "", { "dependencies": { "archiver-utils": "^3.0.4", "compress-commons": "^4.1.2", "readable-stream": "^3.6.0" } }, "sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ=="], + + "archiver-utils/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + + "glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], + + "string_decoder/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "zip-stream/archiver-utils": ["archiver-utils@3.0.4", "", { "dependencies": { "glob": "^7.2.3", "graceful-fs": "^4.2.0", "lazystream": "^1.0.0", "lodash.defaults": "^4.2.0", "lodash.difference": "^4.5.0", "lodash.flatten": "^4.4.0", "lodash.isplainobject": "^4.0.6", "lodash.union": "^4.6.0", "normalize-path": "^3.0.0", "readable-stream": "^3.6.0" } }, "sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw=="], + + "archiver-utils/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + + "glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + + "lazystream/readable-stream/safe-buffer": ["safe-buffer@5.1.2", "", {}, "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="], + + "lazystream/readable-stream/string_decoder": ["string_decoder@1.1.1", "", { "dependencies": { "safe-buffer": "~5.1.0" } }, "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg=="], + } +} From 4a5429c049e6d1e0bf577836903b4eb65e10a973 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 11 Mar 2025 14:18:19 +0700 Subject: [PATCH 145/184] add data jobdesk in karyawan --- app/Http/Controllers/KaryawanController.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 759eb90..8501a31 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -81,7 +81,20 @@ public function show($id) $user = User::find($id); // load jobdesk $user->load('jobdesk'); - return response()->json($user); + $response = [ + 'id' => $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'is_admin' => strval($user->is_admin), + 'avatar' => $user->avatar, + 'phone' => $user->phone, + 'address' => $user->address, + 'position' => $user->position, + 'total_jobdesk' => $user->jobdesk->count(), + 'jobdesk_on_progress' => $user->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $user->jobdesk->where('status', 'Selesai')->count(), + ]; + return response()->json($response); } public function update(Request $request, $id) From 8b5c4c191d0e53a2ed0849c6a4b1514115423155 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 19 Mar 2025 20:29:42 +0700 Subject: [PATCH 146/184] add validasi bckend --- app/Http/Controllers/OrderController.php | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 719df00..36ccd67 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -173,7 +173,7 @@ public function update(Request $request, Order $order) { $user = $request->user(); - // Jika ada lampiran, hanya validasi lampiran + // Jika ada lampiran, validasi hanya file lampiran if ($request->hasFile('lampiran')) { $request->validate([ 'lampiran' => 'required|mimes:pdf|max:15000', @@ -183,7 +183,10 @@ public function update(Request $request, Order $order) 'lampiran.max' => 'Lampiran tidak boleh lebih besar dari 15MB.', ]); + // Simpan file lampiran baru $filePath = $request->file('lampiran')->store('lampiran', 'public'); + // simpan lengkap dengan asset + $filePath = asset('storage/' . $filePath); // Hapus dokumen lama jika ada if ($order->lampiran) { @@ -193,7 +196,7 @@ public function update(Request $request, Order $order) // Update order dengan lampiran baru $order->update(['lampiran' => $filePath]); } else { - // Validasi data lain jika lampiran tidak ada + // Jika tidak ada lampiran, validasi field lain $validatedData = $request->validate([ 'order_date' => 'required', 'product_id' => 'required', @@ -202,13 +205,19 @@ public function update(Request $request, Order $order) 'payment_method' => 'required', 'meta' => 'nullable', 'customer' => 'required', + ], [ + 'order_date.required' => 'Tanggal pesanan harus diisi.', + 'product_id.required' => 'Produk harus dipilih.', + 'price.required' => 'Harga harus diisi.', + 'payment_method.required' => 'Metode pembayaran harus dipilih.', + 'customer.required' => 'Pelanggan harus diisi.', ]); // Update order dengan data yang sudah divalidasi $order->update($validatedData); } - // Load relasi dan respon + // Load relasi dan siapkan respons $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); $response = [ 'id' => $order->id, From b2ef18d27ab3c490c0dbd3f3c70453ffb7971c40 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 27 Mar 2025 14:50:07 +0700 Subject: [PATCH 147/184] fix lampiran url --- app/Http/Controllers/OrderController.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 36ccd67..3c4c146 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -92,8 +92,9 @@ public function index(Request $request) // Check if pagination should be disabled if ($paginate === 'false') { - // Get all records without pagination + // Get all records without pagination $orders = $query->get()->map(function ($data) use ($user) { + $data['lampiran'] = asset('storage/' . $data->lampiran); return [ 'id' => $data->id, 'no_order' => $data->no_order, @@ -128,6 +129,7 @@ public function index(Request $request) // Paginate results $orders = $query->paginate(25); $orders->getCollection()->transform(function ($data) use ($user) { + $data['lampiran'] = asset('storage/' . $data->lampiran); return [ 'id' => $data->id, 'no_order' => $data->no_order, From 2f860aa4ab7693116b96f21212819b6d9d35e5fa Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 11 Apr 2025 10:40:54 +0700 Subject: [PATCH 148/184] allow jpg in favicon --- app/Http/Controllers/SettingFaviconController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/SettingFaviconController.php b/app/Http/Controllers/SettingFaviconController.php index 07e02b1..85f986b 100644 --- a/app/Http/Controllers/SettingFaviconController.php +++ b/app/Http/Controllers/SettingFaviconController.php @@ -27,7 +27,7 @@ public function index() public function store(Request $request) { $validatedData = $request->validate([ - 'favicon' => 'nullable|image|mimes:png,ico|max:1024', // Maksimal 1MB, hanya PNG atau ICO + 'favicon' => 'nullable|image|mimes:png,ico,jpg|max:1024', // Maksimal 1MB, hanya PNG atau ICO ]); $favicon = []; From 0c8bfa97b86b8dbf40aa1850fb4dd2533eea118d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 15 Apr 2025 19:57:33 +0700 Subject: [PATCH 149/184] fix pdf preview --- app/Http/Controllers/OrderController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 3c4c146..0ed721b 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -94,7 +94,7 @@ public function index(Request $request) if ($paginate === 'false') { // Get all records without pagination $orders = $query->get()->map(function ($data) use ($user) { - $data['lampiran'] = asset('storage/' . $data->lampiran); + $data['lampiran'] = $data->lampiran; return [ 'id' => $data->id, 'no_order' => $data->no_order, @@ -129,7 +129,7 @@ public function index(Request $request) // Paginate results $orders = $query->paginate(25); $orders->getCollection()->transform(function ($data) use ($user) { - $data['lampiran'] = asset('storage/' . $data->lampiran); + $data['lampiran'] = $data->lampiran; return [ 'id' => $data->id, 'no_order' => $data->no_order, From 9e322133988cd986fdb5a3ac470f2508f8ee9a30 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 22 Apr 2025 15:38:48 +0700 Subject: [PATCH 150/184] add consumen register date to API --- app/Http/Controllers/CustomerController.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index c3f381d..95cd03f 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -66,7 +66,8 @@ public function index(Request $request) 'address' => $data->address, 'order_count' => $data->orders->count(), 'orders' => $data->orders, - 'meta' => $data->meta + 'meta' => $data->meta, + 'created_at' => $data->created_at ]; }); } else { @@ -79,7 +80,8 @@ public function index(Request $request) 'address' => $data->address, 'order_count' => $data->orders->count(), 'orders' => $data->orders, - 'meta' => $data->meta + 'meta' => $data->meta, + 'created_at' => $data->created_at ]; }); } @@ -119,7 +121,8 @@ public function store(Request $request) 'address' => $customer->address, 'order_count' => $customer->orders->count(), 'orders' => $customer->orders, - 'meta' => $customer->meta + 'meta' => $customer->meta, + 'created_at' => $customer->created_at ] ]; return response()->json($response); @@ -176,7 +179,8 @@ public function update(Request $request, Customer $customer) 'address' => $customer->address, 'order_count' => $customer->orders->count(), 'orders' => $customer->orders, - 'meta' => $customer->meta + 'meta' => $customer->meta, + 'created_at' => $customer->created_at ] ]; return response()->json($response); From cafb0e20060c063de3eefc4446d9483fc96a64bf Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 22 Apr 2025 21:44:50 +0700 Subject: [PATCH 151/184] add validation message customer api --- app/Http/Controllers/CustomerController.php | 24 ++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 95cd03f..65486a9 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -21,11 +21,21 @@ class CustomerController extends Controller public function index(Request $request) { $paginate = $request->query('paginate'); - $validated = $request->validate([ - 'name' => 'nullable|string|min:3', - 'phone' => 'nullable|string|min:4', - 'bank' => 'nullable|string', - ]); + $validated = $request->validate( + [ + 'name' => 'nullable|string|min:3', + 'phone' => 'nullable|string|min:4', + 'bank' => 'nullable|string', + 'dari' => 'nullable|date', + 'sampai' => 'nullable|date', + ], + [ + 'name.min' => 'Minimal 3 karakter', + 'phone.min' => 'Minimal 4 karakter', + 'dari.date' => 'Format tanggal salah', + 'sampai.date' => 'Format tanggal salah', + ] + ); $query = Customer::with('orders', 'meta'); @@ -55,6 +65,10 @@ public function index(Request $request) } } + if (!empty($validated['dari']) && !empty($validated['sampai'])) { + $query->whereBetween('created_at', [$validated['dari'], $validated['sampai']]); + } + $query->orderBy('created_at', 'desc'); if ($paginate === 'false') { From 72bb8c376087813cf557ab0c8a0f2d64bf8982a2 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 23 Apr 2025 20:29:41 +0700 Subject: [PATCH 152/184] fix filter by date --- app/Http/Controllers/CustomerController.php | 10 +++++++++- app/Http/Controllers/OrderController.php | 13 ++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 65486a9..3ce4159 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -66,7 +66,15 @@ public function index(Request $request) } if (!empty($validated['dari']) && !empty($validated['sampai'])) { - $query->whereBetween('created_at', [$validated['dari'], $validated['sampai']]); + $query->whereBetween('order_date', [$validated['dari'], $validated['sampai']]); + } + + if (!empty($validated['dari']) && empty($validated['sampai'])) { + $query->where('order_date', '>=', $validated['dari']); + } + + if (empty($validated['dari']) && !empty($validated['sampai'])) { + $query->where('order_date', '<=', $validated['sampai']); } $query->orderBy('created_at', 'desc'); diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 0ed721b..a05acdc 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -30,6 +30,8 @@ public function index(Request $request) $name = $request->query('name'); $productQuery = $request->query('product'); $bank = $request->query('bank'); + $dari = $request->query('dari'); + $sampai = $request->query('sampai'); $status = $request->query('status'); $status = isset($status) ? $status : null; $user = $request->user(); @@ -40,7 +42,7 @@ public function index(Request $request) $query->where('customer_id', $customerId); } - if ($name || $productQuery || $bank) { + if ($name || $productQuery || $bank || $dari || $sampai) { $query->whereHas('customer', function ($query) use ($name) { $query->where('name', 'like', '%' . $name . '%'); }); @@ -53,6 +55,15 @@ public function index(Request $request) ->where('meta_value', '=', $bank); }); } + if ($dari && $sampai) { + $query->whereBetween('order_date', [$dari, $sampai]); + } + if ($dari && !$sampai) { + $query->where('order_date', '>=', $dari); + } + if (!$dari && $sampai) { + $query->where('order_date', '<=', $sampai); + } } else { if ($status) { $query->whereDoesntHave('jobdesks', function ($query) use ($status) { From f389e07ad7cf92ff6550acaec75acf7fb436fd3b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 24 Apr 2025 15:11:45 +0700 Subject: [PATCH 153/184] add date filter jobdesk --- app/Http/Controllers/JobdeskController.php | 14 ++++++++++++++ database/seeders/UserSeeder.php | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index d864bb2..70df4a1 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -15,6 +15,8 @@ public function index(Request $request) $status = $request->query('status'); $name = $request->query('name'); $userId = $request->query('user_id'); + $dari = $request->query('dari'); + $sampai = $request->query('sampai'); $user = $request->user(); // Initialize the query @@ -45,6 +47,18 @@ public function index(Request $request) }); } + if ($dari && $sampai) { + $query->whereBetween('order.order_date', [$dari, $sampai]); + } + + if ($dari && !$sampai) { + $query->where('order.order_date', '>=', $dari); + } + + if (!$dari && $sampai) { + $query->where('order.order_date', '<=', $sampai); + } + // Paginate the results $jobdesk = $query->orderBy('id', 'asc')->paginate(25); diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 0835d93..acb52f9 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -17,7 +17,7 @@ public function run() 'avatar' => null, 'phone' => '08123456789', 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Manager', + 'position' => 'Owner', 'password' => Hash::make('password'), ]); User::factory()->create([ From 22da0516acc9eae52ebaf5f9b6359da5493d5d28 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 24 Apr 2025 20:41:32 +0700 Subject: [PATCH 154/184] add default background --- .../Controllers/SettingLoginController.php | 4 ++-- public/assets/bg.jpeg | Bin 0 -> 569090 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 public/assets/bg.jpeg diff --git a/app/Http/Controllers/SettingLoginController.php b/app/Http/Controllers/SettingLoginController.php index 5484815..f545734 100644 --- a/app/Http/Controllers/SettingLoginController.php +++ b/app/Http/Controllers/SettingLoginController.php @@ -16,8 +16,8 @@ public function index() $setting = Setting::where('setting_key', 'background')->first(); $background = $setting ? json_decode($setting->setting_value, true) : []; return response()->json([ - 'color' => $background['color'] ?? null, - 'image' => $background['image'] ?? null, + 'color' => $background['color'] ?? 'rgba(0, 0, 0, 0.1)', + 'image' => $background['image'] ?? asset('assets/bg.jpeg'), 'style' => $background['style'] ?? null ]); } diff --git a/public/assets/bg.jpeg b/public/assets/bg.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..a16c8be2a61988112959a2890dfc07a946631d19 GIT binary patch literal 569090 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
  • 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μ+|Wkx@g|9CRO*QKrbT4YuL9ttRYd-ODKl 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

    ?O8s=&Uh&G*u_;X*dwAFO2QsPq0c?;Ul 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

    Btn!PX%^6Fa zH&RuTwN6BCa&r@pGmJ7f&oR^C4XOW;gMPw|4vJ)OXB)}4J$CU&+3JkqZ(kjBJbAzA z>H0u>?yVaDx#y;l?$SVZEXM4sgCalKBCNvXOCCTGDd~J`^-M=Fe5$=f!*+-y^U%bD zR#6S<78`$nEi!+3XJopnrjfZZeR}GRm{b{~ya;34ZUT~Kz$f48Tr&}Cqc@g=<1Hx@ zMae^>P1yGb5qio?ej~DK#-BgpaSmj8sb*gDK`N*Um!EX1bwB0&dgeHgNXIyVswWRO z)NYI~6CNZZcXI>2m?5~I3x3zF2b>W4donVw3^Xlc4j2m<;9?2E2w8}!^VQ9g&>EJB z9S)raNj!cP+quVM|G0h=`q5k1j4G3bJQEQ28Y7GK3SG3(^JX|5&`U&{rp@7WDw~fC zD>r>@ok>&@+$b{Cmr2E-I5Vs_Ux-BK%hD7je>dWQd9iGTtfZG_Ppqnp&}mj%WNJkAOWV8OL3=9~n3J z;aH=nKRffpDiH`4i>ZT4jM+Y`@lZ|z;y#A86W1W)252VYD772v4ZeND0RJH16vsIr zS0M9*Ij!BSs_cd+qSD6YSWwh*Kd)fJM3%kZ#huLI=|eU~SNpj_UwI|E5fvbSjM#(_ zt8ULBqlypLpTnVr_i^Dn4H5c|pT2}7lE**JSuHo8=%{2`oDNJ|?}Wg@Fg?n+avF>t6K7J?veue zgldzV$UlrZ$_+w-;;_MtYbRaeI%cX1wAcV>STW%gLm+6IAo^NiXl#kzILraQxbDDNbUsUgGhJK39d4VR;wc&}G?m=hsdlOD#yD z`c_HJljP$Nw#4zWwb)!nHr>qmq+-(xR%;8;mMlkY)$G;8OIx3?8{mG!FGwGz5sDW_ z>X>aM`B`mZ({+m|_{-WF)l{>JaI0QhDZC53?A_C30;�txarZ2l&6vFvGzOY6 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%0AYj)EqUJ_YCFgf?;twoQP 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%0A*JId*-67`IzZK$iMKD;lGQ1E%?&Qz}^b5 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,?3EENkWRY?RJw__@>JG!S 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

    &#tFJ{{XeGh_0``E26;KaHMg>|H0EgZ4L{;c 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 U0ITK`jP<{9 literal 0 HcmV?d00001 From 71b31bc4878c46d273995092e07b338531580cb9 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Mon, 28 Apr 2025 10:36:55 +0700 Subject: [PATCH 155/184] fox filter by date --- app/Http/Controllers/CustomerController.php | 24 ++++++++++++--------- app/Http/Controllers/JobdeskController.php | 12 ++++++++--- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 3ce4159..55d65b3 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -15,6 +15,9 @@ class CustomerController extends Controller public $validate = [ 'name' => 'required|string|max:255', 'phone' => 'required|string|max:20', + 'bank' => 'string', + 'dari' => 'date', + 'sampai' => 'date', 'address' => 'required|string', ]; @@ -65,20 +68,21 @@ public function index(Request $request) } } - if (!empty($validated['dari']) && !empty($validated['sampai'])) { - $query->whereBetween('order_date', [$validated['dari'], $validated['sampai']]); - } - - if (!empty($validated['dari']) && empty($validated['sampai'])) { - $query->where('order_date', '>=', $validated['dari']); - } - - if (empty($validated['dari']) && !empty($validated['sampai'])) { - $query->where('order_date', '<=', $validated['sampai']); + if (!empty($validated['dari']) || !empty($validated['sampai'])) { + $query->when(!empty($validated['dari']) && !empty($validated['sampai']), function ($q) use ($validated) { + $q->whereBetween('created_at', [$validated['dari'], $validated['sampai']]); + }) + ->when(!empty($validated['dari']) && empty($validated['sampai']), function ($q) use ($validated) { + $q->where('created_at', '>=', $validated['dari']); + }) + ->when(empty($validated['dari']) && !empty($validated['sampai']), function ($q) use ($validated) { + $q->where('created_at', '<=', $validated['sampai']); + }); } $query->orderBy('created_at', 'desc'); + if ($paginate === 'false') { $customers = $query->get()->map(function ($data) { return [ diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 70df4a1..295567c 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -48,15 +48,21 @@ public function index(Request $request) } if ($dari && $sampai) { - $query->whereBetween('order.order_date', [$dari, $sampai]); + $query->whereHas('order', function ($q) use ($dari, $sampai) { + $q->whereBetween('order_date', [$dari, $sampai]); + }); } if ($dari && !$sampai) { - $query->where('order.order_date', '>=', $dari); + $query->whereHas('order', function ($q) use ($dari) { + $q->where('order_date', '>=', $dari); + }); } if (!$dari && $sampai) { - $query->where('order.order_date', '<=', $sampai); + $query->whereHas('order', function ($q) use ($sampai) { + $q->where('order_date', '<=', $sampai); + }); } // Paginate the results From f7c40b8c53dc31ebd20a169ba9afc43d4fea3aab Mon Sep 17 00:00:00 2001 From: Imam Tri Date: Fri, 9 May 2025 19:55:49 +0700 Subject: [PATCH 156/184] Update sedder --- database/seeders/UserSeeder.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index acb52f9..5ebbf64 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -12,7 +12,7 @@ public function run() { User::factory()->create([ 'name' => 'Test Admin', - 'email' => 'user1@asistennotaris.com', + 'email' => 'user1@example.com', 'is_admin' => true, 'avatar' => null, 'phone' => '08123456789', @@ -22,7 +22,7 @@ public function run() ]); User::factory()->create([ 'name' => 'Test Manager', - 'email' => 'user2@asistennotaris.com', + 'email' => 'user2@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', @@ -32,7 +32,7 @@ public function run() ]); User::factory()->create([ 'name' => 'Test Keuangan', - 'email' => 'user3@asistennotaris.com', + 'email' => 'user3@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', @@ -42,7 +42,7 @@ public function run() ]); User::factory()->create([ 'name' => 'Test Staff', - 'email' => 'user4@asistennotaris.com', + 'email' => 'user4@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', @@ -53,7 +53,7 @@ public function run() User::factory()->create([ 'name' => 'Test Staff 2', - 'email' => 'user5@asistennotaris.com', + 'email' => 'user5@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', From 8dcfcbf10aaff9285c71311a2406a84c0bcc4e24 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 23 May 2025 14:11:43 +0700 Subject: [PATCH 157/184] add role --- app/Models/User.php | 3 +- composer.json | 3 +- composer.lock | 89 +++++++- config/permission.php | 202 ++++++++++++++++++ ..._05_23_112118_create_permission_tables.php | 136 ++++++++++++ database/seeders/PositionSeeder.php | 12 ++ database/seeders/UserSeeder.php | 33 +-- 7 files changed, 460 insertions(+), 18 deletions(-) create mode 100644 config/permission.php create mode 100644 database/migrations/2025_05_23_112118_create_permission_tables.php create mode 100644 database/seeders/PositionSeeder.php diff --git a/app/Models/User.php b/app/Models/User.php index 783cbcd..7549694 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -6,11 +6,12 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { /** @use HasFactory<\Database\Factories\UserFactory> */ - use HasFactory, Notifiable; + use HasFactory, Notifiable, HasRoles; /** * The attributes that are mass assignable. diff --git a/composer.json b/composer.json index 87d5460..d94e408 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "php": "^8.2", "laravel/framework": "^11.9", "laravel/sanctum": "^4.0", - "laravel/tinker": "^2.9" + "laravel/tinker": "^2.9", + "spatie/laravel-permission": "^6.18" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/composer.lock b/composer.lock index 8f993e7..4092db9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "785aaa5464fc438ca2615f92095171f0", + "content-hash": "cade82523504e7c46a624c9282288cd0", "packages": [ { "name": "brick/math", @@ -3363,6 +3363,89 @@ ], "time": "2024-04-27T21:32:50+00:00" }, + { + "name": "spatie/laravel-permission", + "version": "6.18.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/laravel-permission.git", + "reference": "3c05f04d12275dfbe462c8b4aae3290e586c2dde" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/laravel-permission/zipball/3c05f04d12275dfbe462c8b4aae3290e586c2dde", + "reference": "3c05f04d12275dfbe462c8b4aae3290e586c2dde", + "shasum": "" + }, + "require": { + "illuminate/auth": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/container": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/contracts": "^8.12|^9.0|^10.0|^11.0|^12.0", + "illuminate/database": "^8.12|^9.0|^10.0|^11.0|^12.0", + "php": "^8.0" + }, + "require-dev": { + "laravel/passport": "^11.0|^12.0", + "laravel/pint": "^1.0", + "orchestra/testbench": "^6.23|^7.0|^8.0|^9.0|^10.0", + "phpunit/phpunit": "^9.4|^10.1|^11.5" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Spatie\\Permission\\PermissionServiceProvider" + ] + }, + "branch-alias": { + "dev-main": "6.x-dev", + "dev-master": "6.x-dev" + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Spatie\\Permission\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Permission handling for Laravel 8.0 and up", + "homepage": "https://github.com/spatie/laravel-permission", + "keywords": [ + "acl", + "laravel", + "permission", + "permissions", + "rbac", + "roles", + "security", + "spatie" + ], + "support": { + "issues": "https://github.com/spatie/laravel-permission/issues", + "source": "https://github.com/spatie/laravel-permission/tree/6.18.0" + }, + "funding": [ + { + "url": "https://github.com/spatie", + "type": "github" + } + ], + "time": "2025-05-14T03:32:23+00:00" + }, { "name": "symfony/clock", "version": "v7.2.0", @@ -8199,12 +8282,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": {}, + "platform-dev": [], "plugin-api-version": "2.6.0" } diff --git a/config/permission.php b/config/permission.php new file mode 100644 index 0000000..f39f6b5 --- /dev/null +++ b/config/permission.php @@ -0,0 +1,202 @@ + [ + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * Eloquent model should be used to retrieve your permissions. Of course, it + * is often just the "Permission" model but you may use whatever you like. + * + * The model you want to use as a Permission model needs to implement the + * `Spatie\Permission\Contracts\Permission` contract. + */ + + 'permission' => Spatie\Permission\Models\Permission::class, + + /* + * When using the "HasRoles" trait from this package, we need to know which + * Eloquent model should be used to retrieve your roles. Of course, it + * is often just the "Role" model but you may use whatever you like. + * + * The model you want to use as a Role model needs to implement the + * `Spatie\Permission\Contracts\Role` contract. + */ + + 'role' => Spatie\Permission\Models\Role::class, + + ], + + 'table_names' => [ + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your roles. We have chosen a basic + * default value but you may easily change it to any table you like. + */ + + 'roles' => 'roles', + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * table should be used to retrieve your permissions. We have chosen a basic + * default value but you may easily change it to any table you like. + */ + + 'permissions' => 'permissions', + + /* + * When using the "HasPermissions" trait from this package, we need to know which + * table should be used to retrieve your models permissions. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'model_has_permissions' => 'model_has_permissions', + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your models roles. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'model_has_roles' => 'model_has_roles', + + /* + * When using the "HasRoles" trait from this package, we need to know which + * table should be used to retrieve your roles permissions. We have chosen a + * basic default value but you may easily change it to any table you like. + */ + + 'role_has_permissions' => 'role_has_permissions', + ], + + 'column_names' => [ + /* + * Change this if you want to name the related pivots other than defaults + */ + 'role_pivot_key' => null, // default 'role_id', + 'permission_pivot_key' => null, // default 'permission_id', + + /* + * Change this if you want to name the related model primary key other than + * `model_id`. + * + * For example, this would be nice if your primary keys are all UUIDs. In + * that case, name this `model_uuid`. + */ + + 'model_morph_key' => 'model_id', + + /* + * Change this if you want to use the teams feature and your related model's + * foreign key is other than `team_id`. + */ + + 'team_foreign_key' => 'team_id', + ], + + /* + * When set to true, the method for checking permissions will be registered on the gate. + * Set this to false if you want to implement custom logic for checking permissions. + */ + + 'register_permission_check_method' => true, + + /* + * When set to true, Laravel\Octane\Events\OperationTerminated event listener will be registered + * this will refresh permissions on every TickTerminated, TaskTerminated and RequestTerminated + * NOTE: This should not be needed in most cases, but an Octane/Vapor combination benefited from it. + */ + 'register_octane_reset_listener' => false, + + /* + * Events will fire when a role or permission is assigned/unassigned: + * \Spatie\Permission\Events\RoleAttached + * \Spatie\Permission\Events\RoleDetached + * \Spatie\Permission\Events\PermissionAttached + * \Spatie\Permission\Events\PermissionDetached + * + * To enable, set to true, and then create listeners to watch these events. + */ + 'events_enabled' => false, + + /* + * Teams Feature. + * When set to true the package implements teams using the 'team_foreign_key'. + * If you want the migrations to register the 'team_foreign_key', you must + * set this to true before doing the migration. + * If you already did the migration then you must make a new migration to also + * add 'team_foreign_key' to 'roles', 'model_has_roles', and 'model_has_permissions' + * (view the latest version of this package's migration file) + */ + + 'teams' => false, + + /* + * The class to use to resolve the permissions team id + */ + 'team_resolver' => \Spatie\Permission\DefaultTeamResolver::class, + + /* + * Passport Client Credentials Grant + * When set to true the package will use Passports Client to check permissions + */ + + 'use_passport_client_credentials' => false, + + /* + * When set to true, the required permission names are added to exception messages. + * This could be considered an information leak in some contexts, so the default + * setting is false here for optimum safety. + */ + + 'display_permission_in_exception' => false, + + /* + * When set to true, the required role names are added to exception messages. + * This could be considered an information leak in some contexts, so the default + * setting is false here for optimum safety. + */ + + 'display_role_in_exception' => false, + + /* + * By default wildcard permission lookups are disabled. + * See documentation to understand supported syntax. + */ + + 'enable_wildcard_permission' => false, + + /* + * The class to use for interpreting wildcard permissions. + * If you need to modify delimiters, override the class and specify its name here. + */ + // 'wildcard_permission' => Spatie\Permission\WildcardPermission::class, + + /* Cache-specific settings */ + + 'cache' => [ + + /* + * By default all permissions are cached for 24 hours to speed up performance. + * When permissions or roles are updated the cache is flushed automatically. + */ + + 'expiration_time' => \DateInterval::createFromDateString('24 hours'), + + /* + * The cache key used to store all permissions. + */ + + 'key' => 'spatie.permission.cache', + + /* + * You may optionally indicate a specific cache driver to use for permission and + * role caching using any of the `store` drivers listed in the cache.php config + * file. Using 'default' here means to use the `default` set in cache.php. + */ + + 'store' => 'default', + ], +]; diff --git a/database/migrations/2025_05_23_112118_create_permission_tables.php b/database/migrations/2025_05_23_112118_create_permission_tables.php new file mode 100644 index 0000000..ce4d9d2 --- /dev/null +++ b/database/migrations/2025_05_23_112118_create_permission_tables.php @@ -0,0 +1,136 @@ +engine('InnoDB'); + $table->bigIncrements('id'); // permission id + $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format) + $table->string('guard_name'); // For MyISAM use string('guard_name', 25); + $table->timestamps(); + + $table->unique(['name', 'guard_name']); + }); + + Schema::create($tableNames['roles'], static function (Blueprint $table) use ($teams, $columnNames) { + // $table->engine('InnoDB'); + $table->bigIncrements('id'); // role id + if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing + $table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable(); + $table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index'); + } + $table->string('name'); // For MyISAM use string('name', 225); // (or 166 for InnoDB with Redundant/Compact row format) + $table->string('guard_name'); // For MyISAM use string('guard_name', 25); + $table->timestamps(); + if ($teams || config('permission.testing')) { + $table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']); + } else { + $table->unique(['name', 'guard_name']); + } + }); + + Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) { + $table->unsignedBigInteger($pivotPermission); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); + + $table->foreign($pivotPermission) + ->references('id') // permission id + ->on($tableNames['permissions']) + ->onDelete('cascade'); + if ($teams) { + $table->unsignedBigInteger($columnNames['team_foreign_key']); + $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index'); + + $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + } else { + $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary'); + } + + }); + + Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) { + $table->unsignedBigInteger($pivotRole); + + $table->string('model_type'); + $table->unsignedBigInteger($columnNames['model_morph_key']); + $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); + + $table->foreign($pivotRole) + ->references('id') // role id + ->on($tableNames['roles']) + ->onDelete('cascade'); + if ($teams) { + $table->unsignedBigInteger($columnNames['team_foreign_key']); + $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index'); + + $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + } else { + $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary'); + } + }); + + Schema::create($tableNames['role_has_permissions'], static function (Blueprint $table) use ($tableNames, $pivotRole, $pivotPermission) { + $table->unsignedBigInteger($pivotPermission); + $table->unsignedBigInteger($pivotRole); + + $table->foreign($pivotPermission) + ->references('id') // permission id + ->on($tableNames['permissions']) + ->onDelete('cascade'); + + $table->foreign($pivotRole) + ->references('id') // role id + ->on($tableNames['roles']) + ->onDelete('cascade'); + + $table->primary([$pivotPermission, $pivotRole], 'role_has_permissions_permission_id_role_id_primary'); + }); + + app('cache') + ->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null) + ->forget(config('permission.cache.key')); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + $tableNames = config('permission.table_names'); + + if (empty($tableNames)) { + throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.'); + } + + Schema::drop($tableNames['role_has_permissions']); + Schema::drop($tableNames['model_has_roles']); + Schema::drop($tableNames['model_has_permissions']); + Schema::drop($tableNames['roles']); + Schema::drop($tableNames['permissions']); + } +}; diff --git a/database/seeders/PositionSeeder.php b/database/seeders/PositionSeeder.php new file mode 100644 index 0000000..7e968fa --- /dev/null +++ b/database/seeders/PositionSeeder.php @@ -0,0 +1,12 @@ + 'admin']); + Role::create(['name' => 'user']); + Role::create(['name' => 'owner']); + Role::create(['name' => 'manager']); + Role::create(['name' => 'keuangan']); + Role::create(['name' => 'staff']); +} \ No newline at end of file diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 5ebbf64..f64df52 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -5,64 +5,71 @@ use Illuminate\Database\Seeder; use App\Models\User; use Illuminate\Support\Facades\Hash; +use Spatie\Permission\Models\Role; class UserSeeder extends Seeder { public function run() { - User::factory()->create([ + // Pastikan roles sudah tersedia + $roles = ['Owner', 'Manager', 'Keuangan', 'Staff']; + foreach ($roles as $role) { + Role::firstOrCreate(['name' => $role]); + } + + $admin = User::factory()->create([ 'name' => 'Test Admin', 'email' => 'user1@example.com', 'is_admin' => true, 'avatar' => null, 'phone' => '08123456789', 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Owner', 'password' => Hash::make('password'), ]); - User::factory()->create([ + $admin->assignRole('owner'); + + $manager = User::factory()->create([ 'name' => 'Test Manager', 'email' => 'user2@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Manager', 'password' => Hash::make('password'), ]); - User::factory()->create([ + $manager->assignRole('manager'); + + $finance = User::factory()->create([ 'name' => 'Test Keuangan', 'email' => 'user3@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Keuangan', 'password' => Hash::make('password'), ]); - User::factory()->create([ + $finance->assignRole('keuangan'); + + $staff1 = User::factory()->create([ 'name' => 'Test Staff', 'email' => 'user4@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Staff', 'password' => Hash::make('password'), ]); + $staff1->assignRole('staff'); - User::factory()->create([ + $staff2 = User::factory()->create([ 'name' => 'Test Staff 2', 'email' => 'user5@example.com', 'is_admin' => false, 'avatar' => null, 'phone' => '08123456789', 'address' => 'Jl. Kebon Jeruk No. 1', - 'position' => 'Staff', 'password' => Hash::make('password'), ]); - - // // Membuat 30 pengguna - // User::factory(6)->create(); + $staff2->assignRole('staff'); } } From fb01e41e7ebe17b1e04758136c832c78030cbe01 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 23 May 2025 19:40:06 +0700 Subject: [PATCH 158/184] fix database --- app/Models/JobDesk.php | 36 ------------------- ..._05_23_112118_create_permission_tables.php | 29 +++++++++------ 2 files changed, 18 insertions(+), 47 deletions(-) delete mode 100644 app/Models/JobDesk.php diff --git a/app/Models/JobDesk.php b/app/Models/JobDesk.php deleted file mode 100644 index 7af3452..0000000 --- a/app/Models/JobDesk.php +++ /dev/null @@ -1,36 +0,0 @@ - 'date', // Automatic casting to date - 'tanggal_selesai' => 'date', // Automatic casting to date - ]; - - public function order(): BelongsTo - { - return $this->belongsTo(Order::class); - } - - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } -} diff --git a/database/migrations/2025_05_23_112118_create_permission_tables.php b/database/migrations/2025_05_23_112118_create_permission_tables.php index ce4d9d2..58d90a8 100644 --- a/database/migrations/2025_05_23_112118_create_permission_tables.php +++ b/database/migrations/2025_05_23_112118_create_permission_tables.php @@ -50,7 +50,7 @@ public function up(): void Schema::create($tableNames['model_has_permissions'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotPermission, $teams) { $table->unsignedBigInteger($pivotPermission); - $table->string('model_type'); + $table->string('model_type', 191); $table->unsignedBigInteger($columnNames['model_morph_key']); $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); @@ -62,19 +62,22 @@ public function up(): void $table->unsignedBigInteger($columnNames['team_foreign_key']); $table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index'); - $table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'], - 'model_has_permissions_permission_model_type_primary'); + $table->primary( + [$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary' + ); } else { - $table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'], - 'model_has_permissions_permission_model_type_primary'); + $table->primary( + [$pivotPermission, $columnNames['model_morph_key'], 'model_type'], + 'model_has_permissions_permission_model_type_primary' + ); } - }); Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) { $table->unsignedBigInteger($pivotRole); - $table->string('model_type'); + $table->string('model_type', 191); $table->unsignedBigInteger($columnNames['model_morph_key']); $table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); @@ -86,11 +89,15 @@ public function up(): void $table->unsignedBigInteger($columnNames['team_foreign_key']); $table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index'); - $table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'], - 'model_has_roles_role_model_type_primary'); + $table->primary( + [$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary' + ); } else { - $table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'], - 'model_has_roles_role_model_type_primary'); + $table->primary( + [$pivotRole, $columnNames['model_morph_key'], 'model_type'], + 'model_has_roles_role_model_type_primary' + ); } }); From 59f45a33df1c0b165cf693b21fdd603e6b36e1e4 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 23 May 2025 19:42:29 +0700 Subject: [PATCH 159/184] remove jobdesk factory --- app/Models/Jobdesk.php | 36 +++++++++++++++++++++++++++ database/factories/JobDeskFactory.php | 32 ------------------------ 2 files changed, 36 insertions(+), 32 deletions(-) create mode 100644 app/Models/Jobdesk.php delete mode 100644 database/factories/JobDeskFactory.php diff --git a/app/Models/Jobdesk.php b/app/Models/Jobdesk.php new file mode 100644 index 0000000..24f6e2c --- /dev/null +++ b/app/Models/Jobdesk.php @@ -0,0 +1,36 @@ + 'date', // Automatic casting to date + 'tanggal_selesai' => 'date', // Automatic casting to date + ]; + + public function order(): BelongsTo + { + return $this->belongsTo(Order::class); + } + + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } +} diff --git a/database/factories/JobDeskFactory.php b/database/factories/JobDeskFactory.php deleted file mode 100644 index 937d97e..0000000 --- a/database/factories/JobDeskFactory.php +++ /dev/null @@ -1,32 +0,0 @@ - - */ -class JobdeskFactory extends Factory -{ - /** - * Define the model's default state. - * - * @return array - */ - public function definition(): array - { - $status = random_int(1, 100) <= 80 ? 'Selesai' : fake()->randomElement(['Masuk', 'Progress']); - $staffs = User::where('position', 'Staff')->get(); - return [ - 'order_id' => fake()->numberBetween(1, 10), - 'description' => fake()->sentence(), - 'user_id' => $staffs->random()->id, - 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, - 'tanggal_selesai' => $status === 'Selesai' ? now() : null, - 'status' => $status - ]; - } -} From 98d39c6c649ad02bf2f3620f38b1cb9049860c44 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 23 May 2025 21:46:54 +0700 Subject: [PATCH 160/184] rename jobdesk factory --- database/factories/JobdeskFactory.php | 32 +++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 database/factories/JobdeskFactory.php diff --git a/database/factories/JobdeskFactory.php b/database/factories/JobdeskFactory.php new file mode 100644 index 0000000..bb28944 --- /dev/null +++ b/database/factories/JobdeskFactory.php @@ -0,0 +1,32 @@ + + */ +class JobdeskFactory extends Factory +{ + /** + * Define the model's default state. + * + * @return array + */ + public function definition(): array + { + $status = random_int(1, 100) <= 80 ? 'Selesai' : fake()->randomElement(['Masuk', 'Progress']); + $staffs = User::where('position', 'Staff')->get(); + return [ + 'order_id' => fake()->numberBetween(1, 10), + 'description' => fake()->sentence(), + 'user_id' => $staffs->random()->id, + 'tanggal_pengerjaan' => $status !== 'Masuk' ? now()->subDays(fake()->numberBetween(5, 10)) : null, + 'tanggal_selesai' => $status === 'Selesai' ? now() : null, + 'status' => $status + ]; + } +} From f6f72d3ec57d4679ef58af95ae0e51d84d917ed2 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 24 May 2025 21:33:20 +0700 Subject: [PATCH 161/184] add role controller --- app/Http/Controllers/RoleController.php | 49 +++++++++++++++++++++++++ routes/api.php | 4 +- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 app/Http/Controllers/RoleController.php diff --git a/app/Http/Controllers/RoleController.php b/app/Http/Controllers/RoleController.php new file mode 100644 index 0000000..b7cd54e --- /dev/null +++ b/app/Http/Controllers/RoleController.php @@ -0,0 +1,49 @@ +validate([ + 'name' => 'required|string|unique:roles,name', + 'guard_name' => 'nullable|string', + ]); + + return Role::create([ + 'name' => $validated['name'], + 'guard_name' => $validated['guard_name'] ?? 'web', + ]); + } + + public function show(Role $role) + { + return $role; + } + + public function update(Request $request, Role $role) + { + $validated = $request->validate([ + 'name' => 'required|string|unique:roles,name,' . $role->id, + ]); + + $role->update($validated); + + return $role; + } + + public function destroy(Role $role) + { + $role->delete(); + return response()->noContent(); + } +} diff --git a/routes/api.php b/routes/api.php index c492c78..1f88c5b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -20,6 +20,7 @@ SettingFaviconController, PostController, CategoryController, + RoleController, Auth\ProfileController }; @@ -79,6 +80,7 @@ 'customers' => CustomerController::class, 'settings' => SettingController::class, 'products' => ProductController::class, - 'metas' => MetaController::class + 'metas' => MetaController::class, + 'roles' => RoleController::class ]); }); From 38393b986c8be9a76dc1cb148d27e319fcaebce1 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 24 May 2025 22:18:52 +0700 Subject: [PATCH 162/184] fix permision --- app/Http/Controllers/RoleController.php | 33 +++++++++++++++-- database/seeders/PermissionSeeder.php | 48 +++++++++++++++++++++++++ database/seeders/PositionSeeder.php | 30 +++++++++++----- routes/api.php | 5 +++ 4 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 database/seeders/PermissionSeeder.php diff --git a/app/Http/Controllers/RoleController.php b/app/Http/Controllers/RoleController.php index b7cd54e..8ac11d0 100644 --- a/app/Http/Controllers/RoleController.php +++ b/app/Http/Controllers/RoleController.php @@ -3,13 +3,15 @@ namespace App\Http\Controllers; use Spatie\Permission\Models\Role; +use Spatie\Permission\Models\Permission; use Illuminate\Http\Request; class RoleController extends Controller { public function index() { - return Role::all(); // bisa ditambahkan filter/pagination + $roles = Role::with('permissions')->get(); + return $roles; } public function store(Request $request) @@ -17,27 +19,52 @@ public function store(Request $request) $validated = $request->validate([ 'name' => 'required|string|unique:roles,name', 'guard_name' => 'nullable|string', + 'capabilities' => 'nullable|array', // tambahkan validasi capabilities + 'capabilities.*' => 'string|exists:permissions,name', // pastikan permission ada ]); - return Role::create([ + $role = Role::create([ 'name' => $validated['name'], 'guard_name' => $validated['guard_name'] ?? 'web', ]); + + // Sinkronkan capabilities (permissions) jika tersedia + if (isset($validated['capabilities'])) { + $permissions = Permission::whereIn('name', $validated['capabilities'])->get(); + $role->syncPermissions($permissions); + } + + return $role; } public function show(Role $role) { + $role->load('permissions'); // <= tambahkan ini juga return $role; } public function update(Request $request, Role $role) { + // Validasi nama role $validated = $request->validate([ 'name' => 'required|string|unique:roles,name,' . $role->id, + 'capabilities' => 'nullable|array', // tambahkan validasi capabilities + 'capabilities.*' => 'string|exists:permissions,name', // pastikan permission ada ]); - $role->update($validated); + // Update nama role + $role->update([ + 'name' => $validated['name'], + 'guard_name' => $validated['guard_name'] ?? 'web', + ]); + // Sinkronkan capabilities (permissions) jika tersedia + if (isset($validated['capabilities'])) { + $permissions = Permission::whereIn('name', $validated['capabilities'])->get(); + $role->syncPermissions($permissions); + } + // Sinkronkan capabilities (permissions) jika tersedia + $role->syncPermissions($permissions); return $role; } diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php new file mode 100644 index 0000000..032be1a --- /dev/null +++ b/database/seeders/PermissionSeeder.php @@ -0,0 +1,48 @@ + $perm, 'guard_name' => 'web']); + } + } +} diff --git a/database/seeders/PositionSeeder.php b/database/seeders/PositionSeeder.php index 7e968fa..7d92bf8 100644 --- a/database/seeders/PositionSeeder.php +++ b/database/seeders/PositionSeeder.php @@ -1,12 +1,26 @@ 'admin']); - Role::create(['name' => 'user']); - Role::create(['name' => 'owner']); - Role::create(['name' => 'manager']); - Role::create(['name' => 'keuangan']); - Role::create(['name' => 'staff']); -} \ No newline at end of file + public function run(): void + { + $roles = [ + 'admin', + 'user', + 'owner', + 'manager', + 'keuangan', + 'staff', + ]; + + foreach ($roles as $role) { + Role::firstOrCreate([ + 'name' => $role, + 'guard_name' => 'web', // default guard + ]); + } + } +} diff --git a/routes/api.php b/routes/api.php index 1f88c5b..d0dd87d 100644 --- a/routes/api.php +++ b/routes/api.php @@ -23,6 +23,7 @@ RoleController, Auth\ProfileController }; +use Spatie\Permission\Models\Permission; // Routes tanpa middleware Route::get('/settings/background', [SettingLoginController::class, 'index']); @@ -49,6 +50,10 @@ Route::get('/permissions', [PermissionController::class, 'index']); Route::post('/user/{user}/permissions', [PermissionController::class, 'update']); + Route::get('/capabilities', function () { + return Permission::select('id', 'name')->get(); + }); + // Settings Route::prefix('settings')->group(function () { Route::controller(SettingLoginController::class)->group(function () { From b7b4563c789f1cf2674cc2bf18cf080a80d3785f Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 25 May 2025 11:17:04 +0700 Subject: [PATCH 163/184] change position to role --- .../Controllers/Auth/ProfileController.php | 6 +-- app/Http/Controllers/DashboardController.php | 12 +++--- app/Http/Controllers/JobdeskController.php | 2 +- app/Http/Controllers/KaryawanController.php | 42 +++++++------------ app/Http/Controllers/OrderController.php | 20 ++++----- app/Http/Controllers/UserController.php | 2 +- .../Requests/Auth/ProfileUpdateRequest.php | 2 +- app/Models/User.php | 2 +- database/factories/JobdeskFactory.php | 2 +- database/factories/UserFactory.php | 2 +- .../0001_01_01_000000_create_users_table.php | 2 +- ...rename_position_to_role_in_users_table.php | 27 ++++++++++++ .../{PositionSeeder.php => RoleSeeder.php} | 4 +- 13 files changed, 70 insertions(+), 55 deletions(-) create mode 100644 database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php rename database/seeders/{PositionSeeder.php => RoleSeeder.php} (85%) diff --git a/app/Http/Controllers/Auth/ProfileController.php b/app/Http/Controllers/Auth/ProfileController.php index c79bfb8..24c7ea6 100644 --- a/app/Http/Controllers/Auth/ProfileController.php +++ b/app/Http/Controllers/Auth/ProfileController.php @@ -47,9 +47,9 @@ public function update(ProfileUpdateRequest $request) unset($validated['password']); } - //abaikan position jika diisi selain oleh is_admin - if (isset($validated['position']) && $user->is_admin !== 1) { - unset($validated['position']); + //abaikan role jika diisi selain oleh is_admin + if (isset($validated['role']) && $user->is_admin !== 1) { + unset($validated['role']); } // Update profil pengguna diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 48e4f87..8617233 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -38,12 +38,12 @@ public function index(Request $request) $data = [ 'total_customers' => $totalCustomers, 'order_bulan_ini' => $orderBulanIni, - 'total_orders' => $user->position !== 'Staff' ? $totalOrders : 0, - 'total_pendapatan' => $user->position !== 'Staff' ? $totalPendapatan : 0, - 'pendapatan_bulan_ini' => $user->position !== 'Staff' ? $pendapatanBulanIni : 0, - 'pendapatan_bulan_sebelumnya' => $user->position !== 'Staff' ? $pendapatanBulanSebelumnya : 0, - 'total_tagihan' => $user->position !== 'Staff' ? $totalTagihan : 0, - 'total_tagihan_bulan_ini' => $user->position !== 'Staff' ? $totalTagihanBulanIni : 0, + 'total_orders' => $user->role !== 'staff' ? $totalOrders : 0, + 'total_pendapatan' => $user->role !== 'staff' ? $totalPendapatan : 0, + 'pendapatan_bulan_ini' => $user->role !== 'staff' ? $pendapatanBulanIni : 0, + 'pendapatan_bulan_sebelumnya' => $user->role !== 'staff' ? $pendapatanBulanSebelumnya : 0, + 'total_tagihan' => $user->role !== 'staff' ? $totalTagihan : 0, + 'total_tagihan_bulan_ini' => $user->role !== 'staff' ? $totalTagihanBulanIni : 0, 'total_karyawan' => $totalKaryawan, 'total_jobdesks' => [ 'Masuk' => (int) $totalJobdesk->get('Masuk', 0), diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 295567c..290e0d2 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -27,7 +27,7 @@ public function index(Request $request) $query->where('order_id', $orderId); } - if (in_array($user->position, ['Staff'])) { + if (in_array($user->role, ['staff'])) { $query->where('user_id', $user->id); } diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 8501a31..115a7f2 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -5,10 +5,10 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\Facades\Hash; use App\Models\User; use App\Models\Jobdesk; - class KaryawanController extends Controller { use AuthorizesRequests; @@ -17,27 +17,21 @@ public function index(Request $request) { $paginate = $request->query('paginate'); $name = $request->query('name'); - $position = $request->query('position'); + $role = $request->query('role'); - // Query dasar semua user dengan relasi jobdesk $query = User::with('jobdesk'); - // Filter berdasarkan name jika ada if ($name && strlen($name) > 2) { $query->where('name', 'like', '%' . $name . '%'); } - // Filter berdasarkan position jika ada - if ($position) { - $query->where('position', $position); + if ($role) { + $query->where('role', $role); } - // Sorting descending berdasarkan created_at $query->orderBy('created_at', 'desc'); - // Check if pagination should be disabled if ($paginate === 'false') { - // Get all records without pagination $users = $query->get()->map(function ($data) { return [ 'id' => $data->id, @@ -47,14 +41,13 @@ public function index(Request $request) 'avatar' => $data->avatar, 'phone' => $data->phone, 'address' => $data->address, - 'position' => $data->position, + 'role' => $data->role, 'total_jobdesk' => $data->jobdesk->count(), 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), ]; }); } else { - // Paginate results $users = $query->paginate(25); $users->getCollection()->transform(function ($data) { return [ @@ -65,7 +58,7 @@ public function index(Request $request) 'avatar' => $data->avatar, 'phone' => $data->phone, 'address' => $data->address, - 'position' => $data->position, + 'role' => $data->role, 'total_jobdesk' => $data->jobdesk->count(), 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), @@ -79,8 +72,8 @@ public function index(Request $request) public function show($id) { $user = User::find($id); - // load jobdesk $user->load('jobdesk'); + $response = [ 'id' => $user->id, 'name' => $user->name, @@ -89,11 +82,12 @@ public function show($id) 'avatar' => $user->avatar, 'phone' => $user->phone, 'address' => $user->address, - 'position' => $user->position, + 'role' => $user->role, 'total_jobdesk' => $user->jobdesk->count(), 'jobdesk_on_progress' => $user->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $user->jobdesk->where('status', 'Selesai')->count(), ]; + return response()->json($response); } @@ -103,18 +97,16 @@ public function update(Request $request, $id) $requested_user = $request->user(); $this->authorize('update', $user); - // Validasi manual $validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|max:255|unique:users,email,' . $id, 'phone' => 'required|string', 'address' => 'required|string', - 'position' => 'nullable|string', + 'role' => 'nullable|string', 'password' => 'nullable|string|min:8|confirmed', 'avatar' => 'nullable', ]); - // Handle Avatar if ($request->hasFile('avatar')) { if ($user->avatar) { Storage::disk('public')->delete($user->avatar); @@ -125,24 +117,19 @@ public function update(Request $request, $id) unset($validated['avatar']); } - // Handle Password if (!empty($validated['password'])) { $validated['password'] = Hash::make($validated['password']); } else { unset($validated['password']); } - // Check for position update - if ($requested_user->is_admin !== 1 && isset($validated['position'])) { - $validated['position'] = $user->position; + if ($requested_user->is_admin !== 1 && isset($validated['role'])) { + $validated['role'] = $user->role; } - // Update user $updated = $user->update($validated); - // Check if the update was successful if ($updated) { - // Retrieve the updated user data $data = User::find($id); return response()->json($data, 200); } else { @@ -157,12 +144,11 @@ public function store(Request $request) 'email' => 'required|email|max:255|unique:users,email', 'phone' => 'required|string', 'address' => 'required|string', - 'position' => 'nullable|string', + 'role' => 'nullable|string', 'password' => 'required|string|min:8|confirmed', 'avatar' => 'nullable', ]); - // Abaikan 'avatar' jika merupakan string, hanya lanjutkan jika file if (is_string($request->avatar)) { unset($validated['avatar']); } elseif ($request->hasFile('avatar')) { @@ -181,7 +167,7 @@ public function store(Request $request) 'avatar' => $data->avatar, 'phone' => $data->phone, 'address' => $data->address, - 'position' => $data->position, + 'role' => $data->role, 'total_jobdesk' => $data->jobdesk->count(), 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index a05acdc..6a2e523 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -112,9 +112,9 @@ public function index(Request $request) 'customer_id' => $data->customer->id ?? null, 'order_date' => $data->order_date, 'product_id' => $data->product->id ?? null, - 'price' => $user->position !== 'Staff' ? $data->price : 0, + 'price' => $user->role !== 'staff' ? $data->price : 0, 'payment_method' => $data->payment_method, - 'paid' => $user->position !== 'Staff' ? $data->paid : 0, + 'paid' => $user->role !== 'staff' ? $data->paid : 0, 'meta' => $data->meta, 'lampiran' => $data->lampiran, 'jobdesk_count' => $data->jobdesks()->count(), @@ -147,9 +147,9 @@ public function index(Request $request) 'customer_id' => $data->customer->id ?? null, 'order_date' => $data->order_date, 'product_id' => $data->product->id ?? null, - 'price' => $user->position !== 'Staff' ? $data->price : 0, + 'price' => $user->role !== 'staff' ? $data->price : 0, 'payment_method' => $data->payment_method, - 'paid' => $user->position !== 'Staff' ? $data->paid : 0, + 'paid' => $user->role !== 'staff' ? $data->paid : 0, 'meta' => $data->meta, 'lampiran' => $data->lampiran, 'jobdesk_count' => $data->jobdesks()->count(), @@ -169,7 +169,7 @@ public function index(Request $request) 'description' => $data->product->description, 'meta_products' => $data->product->metaProducts->pluck('meta'), ] : null, - 'position' => $user->position, + 'role' => $user->role, ]; }); } @@ -238,9 +238,9 @@ public function update(Request $request, Order $order) 'customer_id' => $order->customer->id, 'order_date' => $order->order_date, 'product_id' => $order->product->id, - 'price' => $user->position !== 'Staff' ? $order->price : 0, + 'price' => $user->role !== 'staff' ? $order->price : 0, 'payment_method' => $order->payment_method, - 'paid' => $user->position !== 'Staff' ? $order->paid : 0, + 'paid' => $user->role !== 'staff' ? $order->paid : 0, 'meta' => $order->meta, 'lampiran' => $order->lampiran, 'jobdesk_count' => $order->jobdesks()->count(), @@ -287,7 +287,7 @@ public function store(Request $request) $order = Order::create($validator->validated()); $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); - $users = User::where('is_admin', 1)->orWhere('position', 'owner')->get(); + $users = User::where('is_admin', 1)->orWhere('role', 'owner')->get(); Notification::send($users, new NewOrderNotification($order)); $response = [ 'id' => $order->id, @@ -295,9 +295,9 @@ public function store(Request $request) 'customer_id' => $order->customer->id, 'order_date' => $order->order_date, 'product_id' => $order->product->id, - 'price' => $user->position !== 'Staff' ? $order->price : 0, + 'price' => $user->role !== 'staff' ? $order->price : 0, 'payment_method' => $order->payment_method, - 'paid' => $user->position !== 'Staff' ? $order->paid : 0, + 'paid' => $user->role !== 'staff' ? $order->paid : 0, 'meta' => $order->meta, 'lampiran' => $order->lampiran, 'jobdesk_count' => $order->jobdesks()->count(), diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 7ba70f4..3ce567c 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -20,7 +20,7 @@ public function index(Request $request) 'avatar' => $user->avatar, 'phone' => $user->phone, 'address' => $user->address, - 'position' => $user->position, + 'role' => $user->role, 'created_at' => $user->created_at, 'updated_at' => $user->updated_at ]; diff --git a/app/Http/Requests/Auth/ProfileUpdateRequest.php b/app/Http/Requests/Auth/ProfileUpdateRequest.php index fd7edb5..b52407f 100644 --- a/app/Http/Requests/Auth/ProfileUpdateRequest.php +++ b/app/Http/Requests/Auth/ProfileUpdateRequest.php @@ -33,7 +33,7 @@ public function rules(): array ], 'phone' => ['required', 'string'], 'address' => ['required', 'string'], - 'position' => ['nullable', 'string'], + 'role' => ['nullable', 'string'], 'password' => ['nullable', 'string', 'min:8', 'confirmed'], 'avatar' => ['nullable'], ]; diff --git a/app/Models/User.php b/app/Models/User.php index 7549694..614a235 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -26,7 +26,7 @@ class User extends Authenticatable 'avatar', 'phone', 'address', - 'position', + 'role', 'is_admin', ]; diff --git a/database/factories/JobdeskFactory.php b/database/factories/JobdeskFactory.php index bb28944..fd22fd3 100644 --- a/database/factories/JobdeskFactory.php +++ b/database/factories/JobdeskFactory.php @@ -19,7 +19,7 @@ class JobdeskFactory extends Factory public function definition(): array { $status = random_int(1, 100) <= 80 ? 'Selesai' : fake()->randomElement(['Masuk', 'Progress']); - $staffs = User::where('position', 'Staff')->get(); + $staffs = User::where('role', 'staff')->get(); return [ 'order_id' => fake()->numberBetween(1, 10), 'description' => fake()->sentence(), diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index ef6bb47..aa98e2e 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -32,7 +32,7 @@ public function definition(): array 'avatar' => null, 'phone' => fake()->phoneNumber(), 'address' => fake()->address(), - 'position' => fake()->randomElement(['Keuangan', 'Staff', 'Supervisor', 'Owner', 'Manager']), + 'role' => 'user', 'remember_token' => Str::random(10), ]; } diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index cd186e1..8e0089e 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -20,7 +20,7 @@ public function up(): void $table->string('avatar')->nullable(); $table->string('phone')->nullable(); $table->text('address')->nullable(); - $table->string('position')->nullable(); + $table->string('role')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); diff --git a/database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php b/database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php new file mode 100644 index 0000000..3cddbaf --- /dev/null +++ b/database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php @@ -0,0 +1,27 @@ +renameColumn('position', 'role'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->renameColumn('role', 'position'); + }); + } +}; diff --git a/database/seeders/PositionSeeder.php b/database/seeders/RoleSeeder.php similarity index 85% rename from database/seeders/PositionSeeder.php rename to database/seeders/RoleSeeder.php index 7d92bf8..c94829f 100644 --- a/database/seeders/PositionSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -1,5 +1,7 @@ $role, - 'guard_name' => 'web', // default guard + 'guard_name' => 'web', ]); } } From adfd68e6828d6053483b8111a9fc3902465b0d27 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 25 May 2025 16:24:25 +0700 Subject: [PATCH 164/184] fix migration & seeder --- app/Http/Controllers/KaryawanController.php | 7 +++++++ app/Http/Controllers/RoleController.php | 7 +++---- app/Http/Controllers/UserController.php | 1 + database/factories/JobdeskFactory.php | 4 ++-- .../0001_01_01_000000_create_users_table.php | 2 +- database/seeders/DatabaseSeeder.php | 3 +++ database/seeders/PermissionSeeder.php | 19 +++++++++++++++++++ database/seeders/RoleSeeder.php | 1 + database/seeders/UserSeeder.php | 13 +++++++------ 9 files changed, 44 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 115a7f2..99e9c9d 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -130,6 +130,9 @@ public function update(Request $request, $id) $updated = $user->update($validated); if ($updated) { + if ($requested_user->is_admin === 1 && isset($validated['role'])) { + $user->syncRoles([$validated['role']]); + } $data = User::find($id); return response()->json($data, 200); } else { @@ -159,6 +162,10 @@ public function store(Request $request) $validated['password'] = bcrypt($validated['password']); $data = User::create($validated); + if (!empty($validated['role'])) { + $data->assignRole($validated['role']); + } + $response = [ 'id' => $data->id, 'name' => $data->name, diff --git a/app/Http/Controllers/RoleController.php b/app/Http/Controllers/RoleController.php index 8ac11d0..2ee8df3 100644 --- a/app/Http/Controllers/RoleController.php +++ b/app/Http/Controllers/RoleController.php @@ -48,8 +48,8 @@ public function update(Request $request, Role $role) // Validasi nama role $validated = $request->validate([ 'name' => 'required|string|unique:roles,name,' . $role->id, - 'capabilities' => 'nullable|array', // tambahkan validasi capabilities - 'capabilities.*' => 'string|exists:permissions,name', // pastikan permission ada + 'capabilities' => 'nullable|array', + 'capabilities.*' => 'string|exists:permissions,name', ]); // Update nama role @@ -63,8 +63,7 @@ public function update(Request $request, Role $role) $permissions = Permission::whereIn('name', $validated['capabilities'])->get(); $role->syncPermissions($permissions); } - // Sinkronkan capabilities (permissions) jika tersedia - $role->syncPermissions($permissions); + return $role; } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 3ce567c..6bce9e5 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -21,6 +21,7 @@ public function index(Request $request) 'phone' => $user->phone, 'address' => $user->address, 'role' => $user->role, + 'capabilities' => $user->getAllPermissions()->pluck('name'), 'created_at' => $user->created_at, 'updated_at' => $user->updated_at ]; diff --git a/database/factories/JobdeskFactory.php b/database/factories/JobdeskFactory.php index fd22fd3..9e9fc79 100644 --- a/database/factories/JobdeskFactory.php +++ b/database/factories/JobdeskFactory.php @@ -2,10 +2,10 @@ namespace Database\Factories; -use App\Models\Order; use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; + /** * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Jobdesk> */ @@ -19,7 +19,7 @@ class JobdeskFactory extends Factory public function definition(): array { $status = random_int(1, 100) <= 80 ? 'Selesai' : fake()->randomElement(['Masuk', 'Progress']); - $staffs = User::where('role', 'staff')->get(); + $staffs = User::role('staff')->get(); return [ 'order_id' => fake()->numberBetween(1, 10), 'description' => fake()->sentence(), diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index 8e0089e..cd186e1 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -20,7 +20,7 @@ public function up(): void $table->string('avatar')->nullable(); $table->string('phone')->nullable(); $table->text('address')->nullable(); - $table->string('role')->nullable(); + $table->string('position')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index de52d72..a00a8ce 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -7,6 +7,7 @@ use App\Models\Order; use App\Models\Setting; use Illuminate\Database\Seeder; +use Spatie\Permission\Contracts\Role; class DatabaseSeeder extends Seeder { @@ -18,6 +19,8 @@ public function run(): void $this->call([ SettingSeeder::class, + RoleSeeder::class, + PermissionSeeder::class, UserSeeder::class, ProductSeeder::class, ]); diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php index 032be1a..5ae2645 100644 --- a/database/seeders/PermissionSeeder.php +++ b/database/seeders/PermissionSeeder.php @@ -4,6 +4,7 @@ use Spatie\Permission\Models\Permission; use Illuminate\Database\Seeder; +use Spatie\Permission\Models\Role; class PermissionSeeder extends Seeder { @@ -18,31 +19,49 @@ public function run(): void 'menu:roles', 'menu:settings', + 'customer:create', 'customer:read', 'customer:update', 'customer:delete', + 'order:create', 'order:read', 'order:update', 'order:delete', + 'jobdesk:create', + 'jobdesk:read', + 'jobdesk:update', + 'jobdesk:delete', + + 'product:create', 'product:read', 'product:update', 'product:delete', + 'user:create', 'user:read', 'user:update', 'user:delete', + 'role:create', 'role:read', 'role:update', 'role:delete', + 'access:keuangan', + 'setting:update', ]; foreach ($permissions as $perm) { Permission::firstOrCreate(['name' => $perm, 'guard_name' => 'web']); } + + // Buat role admin + $admin = Role::firstOrCreate(['name' => 'admin']); + + // Assign semua permission yang sudah ada ke role admin + $admin->givePermissionTo(Permission::all()); } } diff --git a/database/seeders/RoleSeeder.php b/database/seeders/RoleSeeder.php index c94829f..b70a88c 100644 --- a/database/seeders/RoleSeeder.php +++ b/database/seeders/RoleSeeder.php @@ -4,6 +4,7 @@ use Illuminate\Database\Seeder; use Spatie\Permission\Models\Role; +use App\Models\User; class RoleSeeder extends Seeder { diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index f64df52..947a055 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -6,17 +6,12 @@ use App\Models\User; use Illuminate\Support\Facades\Hash; use Spatie\Permission\Models\Role; +use Spatie\Permission\Models\Permission; class UserSeeder extends Seeder { public function run() { - // Pastikan roles sudah tersedia - $roles = ['Owner', 'Manager', 'Keuangan', 'Staff']; - foreach ($roles as $role) { - Role::firstOrCreate(['name' => $role]); - } - $admin = User::factory()->create([ 'name' => 'Test Admin', 'email' => 'user1@example.com', @@ -71,5 +66,11 @@ public function run() 'password' => Hash::make('password'), ]); $staff2->assignRole('staff'); + + $roleOwner = Role::firstOrCreate(['name' => 'owner']); + $roleOwner->givePermissionTo(Permission::all()); + + $admin->assignRole($roleOwner); // cukup assign role, tidak perlu assign permission ke user langsung + } } From a0f3d2597fe9d9aee279f96ff7521c6089c2ed2b Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 25 May 2025 22:01:47 +0700 Subject: [PATCH 165/184] change role method --- app/Http/Controllers/KaryawanController.php | 8 ++++---- app/Http/Controllers/UserController.php | 2 +- database/factories/UserFactory.php | 1 - ...41_remove_position_to_role_in_users_table.php} | 9 ++------- database/seeders/PermissionSeeder.php | 1 + database/seeders/UserSeeder.php | 15 +++++---------- 6 files changed, 13 insertions(+), 23 deletions(-) rename database/migrations/{2025_05_25_110241_rename_position_to_role_in_users_table.php => 2025_05_25_110241_remove_position_to_role_in_users_table.php} (62%) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 99e9c9d..9821ee3 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -41,7 +41,7 @@ public function index(Request $request) 'avatar' => $data->avatar, 'phone' => $data->phone, 'address' => $data->address, - 'role' => $data->role, + 'role' => $data->roles->pluck('name'), 'total_jobdesk' => $data->jobdesk->count(), 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), @@ -58,7 +58,7 @@ public function index(Request $request) 'avatar' => $data->avatar, 'phone' => $data->phone, 'address' => $data->address, - 'role' => $data->role, + 'role' => $data->roles->pluck('name'), 'total_jobdesk' => $data->jobdesk->count(), 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), @@ -82,7 +82,7 @@ public function show($id) 'avatar' => $user->avatar, 'phone' => $user->phone, 'address' => $user->address, - 'role' => $user->role, + 'role' => $user->roles->pluck('name'), 'total_jobdesk' => $user->jobdesk->count(), 'jobdesk_on_progress' => $user->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $user->jobdesk->where('status', 'Selesai')->count(), @@ -174,7 +174,7 @@ public function store(Request $request) 'avatar' => $data->avatar, 'phone' => $data->phone, 'address' => $data->address, - 'role' => $data->role, + 'role' => $data->roles->pluck('name'), 'total_jobdesk' => $data->jobdesk->count(), 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 6bce9e5..2953a16 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -20,7 +20,7 @@ public function index(Request $request) 'avatar' => $user->avatar, 'phone' => $user->phone, 'address' => $user->address, - 'role' => $user->role, + 'role' => $user->roles->pluck('name'), 'capabilities' => $user->getAllPermissions()->pluck('name'), 'created_at' => $user->created_at, 'updated_at' => $user->updated_at diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index aa98e2e..b3741b6 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -32,7 +32,6 @@ public function definition(): array 'avatar' => null, 'phone' => fake()->phoneNumber(), 'address' => fake()->address(), - 'role' => 'user', 'remember_token' => Str::random(10), ]; } diff --git a/database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php b/database/migrations/2025_05_25_110241_remove_position_to_role_in_users_table.php similarity index 62% rename from database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php rename to database/migrations/2025_05_25_110241_remove_position_to_role_in_users_table.php index 3cddbaf..95527ee 100644 --- a/database/migrations/2025_05_25_110241_rename_position_to_role_in_users_table.php +++ b/database/migrations/2025_05_25_110241_remove_position_to_role_in_users_table.php @@ -11,17 +11,12 @@ public function up(): void { Schema::table('users', function (Blueprint $table) { - $table->renameColumn('position', 'role'); + $table->removeColumn('position'); }); } /** * Reverse the migrations. */ - public function down(): void - { - Schema::table('users', function (Blueprint $table) { - $table->renameColumn('role', 'position'); - }); - } + public function down(): void {} }; diff --git a/database/seeders/PermissionSeeder.php b/database/seeders/PermissionSeeder.php index 5ae2645..779b26d 100644 --- a/database/seeders/PermissionSeeder.php +++ b/database/seeders/PermissionSeeder.php @@ -14,6 +14,7 @@ public function run(): void 'menu:dashboard', 'menu:customers', 'menu:orders', + 'menu:jobdesks', 'menu:products', 'menu:users', 'menu:roles', diff --git a/database/seeders/UserSeeder.php b/database/seeders/UserSeeder.php index 947a055..0e79578 100644 --- a/database/seeders/UserSeeder.php +++ b/database/seeders/UserSeeder.php @@ -21,7 +21,6 @@ public function run() 'address' => 'Jl. Kebon Jeruk No. 1', 'password' => Hash::make('password'), ]); - $admin->assignRole('owner'); $manager = User::factory()->create([ 'name' => 'Test Manager', @@ -32,7 +31,6 @@ public function run() 'address' => 'Jl. Kebon Jeruk No. 1', 'password' => Hash::make('password'), ]); - $manager->assignRole('manager'); $finance = User::factory()->create([ 'name' => 'Test Keuangan', @@ -43,7 +41,6 @@ public function run() 'address' => 'Jl. Kebon Jeruk No. 1', 'password' => Hash::make('password'), ]); - $finance->assignRole('keuangan'); $staff1 = User::factory()->create([ 'name' => 'Test Staff', @@ -54,7 +51,6 @@ public function run() 'address' => 'Jl. Kebon Jeruk No. 1', 'password' => Hash::make('password'), ]); - $staff1->assignRole('staff'); $staff2 = User::factory()->create([ 'name' => 'Test Staff 2', @@ -65,12 +61,11 @@ public function run() 'address' => 'Jl. Kebon Jeruk No. 1', 'password' => Hash::make('password'), ]); - $staff2->assignRole('staff'); - - $roleOwner = Role::firstOrCreate(['name' => 'owner']); - $roleOwner->givePermissionTo(Permission::all()); - - $admin->assignRole($roleOwner); // cukup assign role, tidak perlu assign permission ke user langsung + $admin->assignRole('admin'); + $manager->assignRole('manager'); + $finance->assignRole('keuangan'); + $staff1->assignRole('staff'); + $staff2->assignRole('staff'); } } From 98238f07bf739228f40acfb4054efbbb6c5987d5 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Wed, 4 Jun 2025 21:51:52 +0700 Subject: [PATCH 166/184] add admin seeder --- app/Http/Controllers/OrderController.php | 4 ++- database/seeders/AdminAccessSeeder.php | 41 ++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 database/seeders/AdminAccessSeeder.php diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 6a2e523..1a1024f 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -287,7 +287,9 @@ public function store(Request $request) $order = Order::create($validator->validated()); $order->load('customer', 'jobdesks', 'product', 'product.metaProducts.meta'); - $users = User::where('is_admin', 1)->orWhere('role', 'owner')->get(); + $users = User::whereHas('permissions', function ($query) { + $query->where('name', 'menu:settings'); + })->get(); Notification::send($users, new NewOrderNotification($order)); $response = [ 'id' => $order->id, diff --git a/database/seeders/AdminAccessSeeder.php b/database/seeders/AdminAccessSeeder.php new file mode 100644 index 0000000..c95ba18 --- /dev/null +++ b/database/seeders/AdminAccessSeeder.php @@ -0,0 +1,41 @@ +first(); + + if (!$admin) { + $admin = User::create([ + 'name' => 'Super Admin', + 'email' => $email, + 'is_admin' => true, + 'avatar' => null, + 'phone' => '081111111111', + 'address' => 'Admin Default Access', + 'password' => Hash::make($password), + ]); + + $admin->assignRole('admin'); + echo "Admin user created: $email / $password\n"; + } else { + // Reset password jika user sudah ada + $admin->password = Hash::make($password); + $admin->save(); + echo "Admin user password reset: $email / $password\n"; + } + } +} From 3981030cf3bd6241ee9467d435506c470f553866 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 5 Jun 2025 00:18:14 +0700 Subject: [PATCH 167/184] update karywan role controller --- app/Http/Controllers/KaryawanController.php | 172 +++++++++++--------- app/Models/User.php | 1 - 2 files changed, 99 insertions(+), 74 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 9821ee3..80edbaf 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -6,6 +6,8 @@ use Illuminate\Http\Request; use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Hash; +use Spatie\Permission\Models\Role; +use Spatie\Permission\Models\Permission; use App\Models\User; use App\Models\Jobdesk; @@ -15,58 +17,47 @@ class KaryawanController extends Controller public function index(Request $request) { - $paginate = $request->query('paginate'); + $paginate = $request->boolean('paginate', true); $name = $request->query('name'); - $role = $request->query('role'); - $query = User::with('jobdesk'); + $query = User::with(['roles', 'jobdesk']); + // Filter nama jika lebih dari 2 karakter if ($name && strlen($name) > 2) { $query->where('name', 'like', '%' . $name . '%'); } - if ($role) { - $query->where('role', $role); + $query->orderByDesc('created_at'); + + $transformUser = function ($user) { + return [ + 'id' => $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'is_admin' => strval($user->is_admin), + 'avatar' => $user->avatar, + 'phone' => $user->phone, + 'address' => $user->address, + 'role' => $user->roles->pluck('name'), + 'total_jobdesk' => $user->jobdesk->count(), + 'jobdesk_on_progress' => $user->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $user->jobdesk->where('status', 'Selesai')->count(), + ]; + }; + + if (!$paginate) { + $users = $query->get()->map($transformUser); + return response()->json([ + 'data' => $users, + 'total' => $users->count(), + ]); } - $query->orderBy('created_at', 'desc'); - - if ($paginate === 'false') { - $users = $query->get()->map(function ($data) { - return [ - 'id' => $data->id, - 'name' => $data->name, - 'email' => $data->email, - 'is_admin' => strval($data->is_admin), - 'avatar' => $data->avatar, - 'phone' => $data->phone, - 'address' => $data->address, - 'role' => $data->roles->pluck('name'), - 'total_jobdesk' => $data->jobdesk->count(), - 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), - 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), - ]; - }); - } else { - $users = $query->paginate(25); - $users->getCollection()->transform(function ($data) { - return [ - 'id' => $data->id, - 'name' => $data->name, - 'email' => $data->email, - 'is_admin' => strval($data->is_admin), - 'avatar' => $data->avatar, - 'phone' => $data->phone, - 'address' => $data->address, - 'role' => $data->roles->pluck('name'), - 'total_jobdesk' => $data->jobdesk->count(), - 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), - 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), - ]; - }); - } + // Paginate with transform + $paginated = $query->paginate(25); + $paginated->getCollection()->transform($transformUser); - return response()->json($users); + return response()->json($paginated); } public function show($id) @@ -107,6 +98,7 @@ public function update(Request $request, $id) 'avatar' => 'nullable', ]); + // Handle avatar upload if ($request->hasFile('avatar')) { if ($user->avatar) { Storage::disk('public')->delete($user->avatar); @@ -117,29 +109,49 @@ public function update(Request $request, $id) unset($validated['avatar']); } + // Handle password hashing if (!empty($validated['password'])) { $validated['password'] = Hash::make($validated['password']); } else { unset($validated['password']); } - if ($requested_user->is_admin !== 1 && isset($validated['role'])) { - $validated['role'] = $user->role; - } + // Handle role separately, cek dulu + $roleName = $validated['role'] ?? null; + unset($validated['role']); // jangan ikut update di table users + // Update user data $updated = $user->update($validated); - if ($updated) { - if ($requested_user->is_admin === 1 && isset($validated['role'])) { - $user->syncRoles([$validated['role']]); + if ($updated && $requested_user->is_admin == 1 && $roleName) { + $role = Role::where('name', $roleName)->first(); + if (!$role) { + return response()->json(['message' => 'Role not found'], 404); } - $data = User::find($id); - return response()->json($data, 200); - } else { - return response()->json(['message' => 'Update failed'], 400); + $user->syncRoles([$role->name]); + } + + if ($updated) { + $response = [ + 'id' => $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'is_admin' => strval($user->is_admin), + 'avatar' => $user->avatar, + 'phone' => $user->phone, + 'address' => $user->address, + 'role' => $user->roles->pluck('name'), + 'total_jobdesk' => $user->jobdesk->count(), + 'jobdesk_on_progress' => $user->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $user->jobdesk->where('status', 'Selesai')->count(), + ]; + return response()->json($response, 200); } + + return response()->json(['message' => 'Update failed'], 400); } + public function store(Request $request) { $validated = $request->validate([ @@ -149,38 +161,52 @@ public function store(Request $request) 'address' => 'required|string', 'role' => 'nullable|string', 'password' => 'required|string|min:8|confirmed', - 'avatar' => 'nullable', + 'avatar' => 'nullable|image|max:2048', // disarankan validasi image ]); - if (is_string($request->avatar)) { + // Handle avatar upload + if ($request->hasFile('avatar')) { + $path = $request->file('avatar')->store('avatars', 'public'); + $validated['avatar'] = asset('storage/' . $path); + } else { unset($validated['avatar']); - } elseif ($request->hasFile('avatar')) { - $validated['avatar'] = $request->file('avatar')->store('avatars', 'public'); - $validated['avatar'] = asset('storage/' . $validated['avatar']); } - $validated['password'] = bcrypt($validated['password']); - $data = User::create($validated); + // Hash password + $validated['password'] = Hash::make($validated['password']); - if (!empty($validated['role'])) { - $data->assignRole($validated['role']); + // Tangani role secara terpisah + $roleName = $validated['role'] ?? null; + unset($validated['role']); // jangan masuk ke User::create + + // Create user + $user = User::create($validated); + + // Assign role jika tersedia + if ($roleName) { + $role = Role::where('name', $roleName)->first(); + if (!$role) { + return response()->json(['message' => 'Role not found'], 404); + } + $user->assignRole($role->name); } + // Buat response $response = [ - 'id' => $data->id, - 'name' => $data->name, - 'email' => $data->email, - 'is_admin' => strval($data->is_admin), - 'avatar' => $data->avatar, - 'phone' => $data->phone, - 'address' => $data->address, - 'role' => $data->roles->pluck('name'), - 'total_jobdesk' => $data->jobdesk->count(), - 'jobdesk_on_progress' => $data->jobdesk->where('status', 'Progress')->count(), - 'jobdesk_selesai' => $data->jobdesk->where('status', 'Selesai')->count(), + 'id' => $user->id, + 'name' => $user->name, + 'email' => $user->email, + 'is_admin' => strval($user->is_admin), + 'avatar' => $user->avatar, + 'phone' => $user->phone, + 'address' => $user->address, + 'role' => $user->roles->pluck('name'), + 'total_jobdesk' => $user->jobdesk->count(), + 'jobdesk_on_progress' => $user->jobdesk->where('status', 'Progress')->count(), + 'jobdesk_selesai' => $user->jobdesk->where('status', 'Selesai')->count(), ]; - return response()->json($response, 200); + return response()->json($response, 201); } public function destroy($id) diff --git a/app/Models/User.php b/app/Models/User.php index 614a235..05d3699 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -26,7 +26,6 @@ class User extends Authenticatable 'avatar', 'phone', 'address', - 'role', 'is_admin', ]; From 903b6306822d67b9c8d8faa9c27cb11ab00aec30 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 18 Jul 2025 19:35:53 +0700 Subject: [PATCH 168/184] update user policy --- app/Http/Controllers/KaryawanController.php | 3 ++ app/Policies/UserPolicy.php | 32 +++++++++++---------- package.json | 4 +-- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 80edbaf..0858ddc 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -17,6 +17,7 @@ class KaryawanController extends Controller public function index(Request $request) { + $this->authorize('viewAny', User::class); $paginate = $request->boolean('paginate', true); $name = $request->query('name'); @@ -62,6 +63,7 @@ public function index(Request $request) public function show($id) { + $this->authorize('view', User::find($id)); $user = User::find($id); $user->load('jobdesk'); @@ -154,6 +156,7 @@ public function update(Request $request, $id) public function store(Request $request) { + $this->authorize('create', User::class); $validated = $request->validate([ 'name' => 'required|string|max:255', 'email' => 'required|email|max:255|unique:users,email', diff --git a/app/Policies/UserPolicy.php b/app/Policies/UserPolicy.php index 8cc6c7b..f6b96dc 100644 --- a/app/Policies/UserPolicy.php +++ b/app/Policies/UserPolicy.php @@ -6,27 +6,29 @@ class UserPolicy { - /** - * Create a new policy instance. - */ - public function __construct() + // viewAny + public function viewAny(User $user) { - // + return $user->can('user:read'); } - public function update(User $authUser, User $user) + public function view(User $user, User $model) { - // Memeriksa apakah pengguna yang sedang login adalah pengguna yang sama - // atau jika pengguna tersebut adalah admin - return $authUser->id === $user->id || (int) $authUser->is_admin === 1; + return $user->can('user:read'); } - public function delete(User $authUser, User $user) + public function create(User $user) { - // Memeriksa apakah pengguna yang sedang login adalah pengguna yang sama - // atau jika pengguna tersebut adalah admin - // dan jika user yang dihapus bukan admin - $authUser->is_admin = (int) $authUser->is_admin; - return ($authUser->id === $user->id || $authUser->is_admin === 1) && $user->is_admin !== 1; + return $user->can('user:create'); + } + + public function update(User $user, User $model) + { + return $user->can('user:update'); + } + + public function delete(User $user, User $model) + { + return $user->can('user:delete'); } } diff --git a/package.json b/package.json index faa82d4..0485543 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "larapi", - "version": "1.0.0", - "description": "Aplikasi Laravel untuk API", + "version": "1.0.1", + "description": "Backend Aplikasi Notaris", "main": "index.js", "scripts": { "build": "node src/script.js" From 1098bf388b0d5ba04920d28250af861307f4b753 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 18 Jul 2025 19:41:06 +0700 Subject: [PATCH 169/184] change update user capability --- app/Http/Controllers/KaryawanController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/KaryawanController.php b/app/Http/Controllers/KaryawanController.php index 0858ddc..19e74a1 100644 --- a/app/Http/Controllers/KaryawanController.php +++ b/app/Http/Controllers/KaryawanController.php @@ -125,7 +125,7 @@ public function update(Request $request, $id) // Update user data $updated = $user->update($validated); - if ($updated && $requested_user->is_admin == 1 && $roleName) { + if ($updated && $roleName) { $role = Role::where('name', $roleName)->first(); if (!$role) { return response()->json(['message' => 'Role not found'], 404); From ce2904174a58221b639eacb991973402bb2e737d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 26 Jul 2025 14:28:13 +0700 Subject: [PATCH 170/184] add post seeder --- database/seeders/CategorySeeder.php | 36 +++++++++++ database/seeders/DatabaseSeeder.php | 2 + database/seeders/PostSeeder.php | 95 +++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 database/seeders/CategorySeeder.php create mode 100644 database/seeders/PostSeeder.php diff --git a/database/seeders/CategorySeeder.php b/database/seeders/CategorySeeder.php new file mode 100644 index 0000000..dbb5692 --- /dev/null +++ b/database/seeders/CategorySeeder.php @@ -0,0 +1,36 @@ + $categoryName, + 'slug' => Str::slug($categoryName) + ]); + } + } +} diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index a00a8ce..fa83c9c 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -23,6 +23,8 @@ public function run(): void PermissionSeeder::class, UserSeeder::class, ProductSeeder::class, + CategorySeeder::class, + PostSeeder::class, ]); // Seed customers and orders diff --git a/database/seeders/PostSeeder.php b/database/seeders/PostSeeder.php new file mode 100644 index 0000000..f6c0c41 --- /dev/null +++ b/database/seeders/PostSeeder.php @@ -0,0 +1,95 @@ +isEmpty()) { + $this->call(CategorySeeder::class); + $categories = Category::all(); + } + + // If no users exist, we can't create posts + if ($users->isEmpty()) { + $this->command->info('No users found. Please seed users first.'); + return; + } + + // Sample article titles and content in Indonesian + $articleTitles = [ + 'Tips Memulai Bisnis Online di Era Digital', + 'Panduan Lengkap Belajar Programming untuk Pemula', + 'Resep Masakan Indonesia yang Mudah dan Lezat', + 'Destinasi Wisata Tersembunyi di Indonesia', + 'Manfaat Olahraga Rutin untuk Kesehatan Mental', + 'Tren Fashion Terkini di Indonesia', + 'Cara Mengoptimalkan SEO Website untuk Bisnis', + 'Review Gadget Terbaru 2025', + 'Tips Mengelola Keuangan Pribadi dengan Baik', + 'Perkembangan Teknologi AI di Indonesia', + 'Wisata Kuliner Nusantara yang Wajib Dicoba', + 'Strategi Marketing Digital yang Efektif', + 'Pentingnya Literasi Digital di Era Modern', + 'Cara Memulai Investasi untuk Generasi Milenial', + 'Tren Arsitektur Modern di Indonesia', + ]; + + $contentTemplates = [ + 'Di era digital seperti sekarang ini, banyak peluang yang bisa dimanfaatkan untuk mengembangkan bisnis atau karier. Artikel ini akan membahas berbagai aspek penting yang perlu diketahui, mulai dari dasar-dasar hingga tips praktis yang bisa langsung diterapkan.', + 'Perkembangan teknologi yang pesat telah mengubah cara kita bekerja dan berinteraksi. Dalam konteks ini, penting untuk memahami berbagai tools dan strategi yang dapat membantu kita beradaptasi dengan perubahan zaman.', + 'Indonesia memiliki kekayaan budaya dan tradisi yang luar biasa. Hal ini tercermin dalam berbagai aspek kehidupan, mulai dari kuliner, seni, hingga cara hidup masyarakatnya. Mari kita eksplorasi lebih dalam tentang keunikan Indonesia.', + 'Kesehatan dan well-being menjadi prioritas utama di masa modern ini. Dengan gaya hidup yang semakin sibuk, penting untuk menemukan keseimbangan antara produktivitas dan kesehatan mental serta fisik.', + 'Dunia bisnis terus berkembang dengan munculnya berbagai inovasi dan teknologi baru. Para entrepreneur perlu memahami tren terkini dan strategi yang efektif untuk dapat bersaing di pasar yang kompetitif.', + ]; + + // Create 50 sample posts + for ($i = 0; $i < 50; $i++) { + $title = $faker->randomElement($articleTitles) . ' - ' . $faker->words(2, true); + $slug = Str::slug($title); + + // Make sure slug is unique + $originalSlug = $slug; + $counter = 1; + while (Post::where('slug', $slug)->exists()) { + $slug = $originalSlug . '-' . $counter; + $counter++; + } + + $content = $faker->randomElement($contentTemplates); + $content .= "\n\n" . $faker->paragraphs(4, true); + $content .= "\n\n## Kesimpulan\n\n" . $faker->paragraph(3); + + Post::create([ + 'title' => $title, + 'content' => $content, + 'slug' => $slug, + 'user_id' => $users->random()->id, + 'category_id' => $categories->random()->id, + 'featured_image' => $faker->optional(0.7)->imageUrl(800, 400, 'business'), + 'created_at' => $faker->dateTimeBetween('-6 months', 'now'), + 'updated_at' => now(), + ]); + } + + $this->command->info('50 posts have been created successfully!'); + } +} From 35a9eedf6ae75b401c632a4cb021e51ccbcff0ec Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 26 Jul 2025 21:31:57 +0700 Subject: [PATCH 171/184] update jobdesk controller --- app/Http/Controllers/JobdeskController.php | 471 ++++++++++++++++++--- app/Http/Controllers/OrderController.php | 354 ++++++++++------ routes/api.php | 6 + 3 files changed, 659 insertions(+), 172 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 290e0d2..d5b8731 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -11,66 +11,141 @@ class JobdeskController extends Controller { public function index(Request $request) { - $orderId = $request->query('order_id'); - $status = $request->query('status'); - $name = $request->query('name'); - $userId = $request->query('user_id'); - $dari = $request->query('dari'); - $sampai = $request->query('sampai'); - $user = $request->user(); - - // Initialize the query - $query = Jobdesk::with('order', 'order.customer', 'user', 'order.product'); - - // Filter by order_id if provided - if ($orderId) { - $query->where('order_id', $orderId); - } + try { + $orderId = $request->query('order_id'); + $status = $request->query('status'); + $name = $request->query('name'); + $userId = $request->query('user_id'); + $dari = $request->query('dari'); + $sampai = $request->query('sampai'); + $user = $request->user(); - if (in_array($user->role, ['staff'])) { - $query->where('user_id', $user->id); - } + // Optimized eager loading with selective fields + $query = Jobdesk::with([ + 'order:id,no_order,customer_id,product_id,order_date', + 'order.customer:id,name,phone,address', + 'order.product:id,name,category,description', + 'user:id,name,email' // Removed 'role' column + ]) + ->select([ + 'id', + 'order_id', + 'user_id', + 'description', + 'status', + 'tanggal_pengerjaan', + 'tanggal_selesai', + 'created_at', + 'updated_at' + ]); - // Filter by status if provided - if ($status) { - $query->where('status', $status); - } + // Filter by order_id if provided + if ($orderId && $orderId !== '') { + $query->where('order_id', $orderId); + } - // Filter by user_id if provided - if ($userId) { - $query->where('user_id', $userId); - } + // Role-based filtering + if (in_array($user->role, ['staff'])) { + $query->where('user_id', $user->id); + } - if ($name && strlen($name) > 2) { - $query->whereHas('order.customer', function ($query) use ($name) { - $query->where('name', 'like', '%' . $name . '%'); - }); - } + // Filter by status if provided + if ($status && $status !== '') { + $query->where('status', $status); + } - if ($dari && $sampai) { - $query->whereHas('order', function ($q) use ($dari, $sampai) { - $q->whereBetween('order_date', [$dari, $sampai]); - }); - } + // Filter by user_id if provided + if ($userId && $userId !== '') { + $query->where('user_id', $userId); + } - if ($dari && !$sampai) { - $query->whereHas('order', function ($q) use ($dari) { - $q->where('order_date', '>=', $dari); - }); - } + // Search by customer name (minimum 3 characters) + if ($name && strlen($name) > 2) { + $query->whereHas('order.customer', function ($query) use ($name) { + $query->where('name', 'like', '%' . $name . '%'); + }); + } - if (!$dari && $sampai) { - $query->whereHas('order', function ($q) use ($sampai) { - $q->where('order_date', '<=', $sampai); + // Date range filters + if ($dari && $sampai) { + $query->whereHas('order', function ($q) use ($dari, $sampai) { + $q->whereBetween('order_date', [ + date('Y-m-d', strtotime($dari)), + date('Y-m-d', strtotime($sampai)) + ]); + }); + } elseif ($dari) { + $query->whereHas('order', function ($q) use ($dari) { + $q->where('order_date', '>=', date('Y-m-d', strtotime($dari))); + }); + } elseif ($sampai) { + $query->whereHas('order', function ($q) use ($sampai) { + $q->where('order_date', '<=', date('Y-m-d', strtotime($sampai))); + }); + } + + // Get total counts for stats (without filters for global stats) + try { + $totalCounts = $this->getGlobalStatusCounts($user); + } catch (\Exception $e) { + // Fallback to simple counts if there's an error + $totalCounts = [ + 'total' => 0, + 'masuk' => 0, + 'progress' => 0, + 'selesai' => 0, + 'completion_rate' => 0 + ]; + } + + // Order and paginate + $jobdesks = $query->orderBy('id', 'desc')->paginate(25); + + // Transform data for frontend + $jobdesks->through(function ($jobdesk) use ($user) { + try { + return $this->formatJobdeskResponse($jobdesk, $user); + } catch (\Exception $e) { + // Fallback to basic response if formatting fails + return [ + 'id' => $jobdesk->id, + 'order_id' => $jobdesk->order_id, + 'user_id' => $jobdesk->user_id, + 'description' => $jobdesk->description, + 'status' => $jobdesk->status, + 'tanggal_pengerjaan' => $jobdesk->tanggal_pengerjaan, + 'tanggal_selesai' => $jobdesk->tanggal_selesai, + 'created_at' => $jobdesk->created_at, + 'updated_at' => $jobdesk->updated_at, + 'order' => $jobdesk->order, + 'user' => $jobdesk->user, + 'error' => 'Formatting error: ' . $e->getMessage() + ]; + } }); - } - // Paginate the results - $jobdesk = $query->orderBy('id', 'asc')->paginate(25); + // Add meta information for frontend + $response = $jobdesks->toArray(); + $response['status_counts'] = $totalCounts; + $response['current_filter'] = [ + 'status' => $status, + 'order_id' => $orderId, + 'user_id' => $userId, + 'name' => $name, + 'dari' => $dari, + 'sampai' => $sampai + ]; - return response()->json($jobdesk); + return response()->json($response); + } catch (\Exception $e) { + return response()->json([ + 'message' => 'Server Error', + 'error' => $e->getMessage(), + 'line' => $e->getLine(), + 'file' => basename($e->getFile()) + ], 500); + } } - public function store(Request $request) { try { @@ -87,8 +162,13 @@ public function store(Request $request) $validatedData['tanggal_selesai'] = $validatedData['tanggal_selesai'] ? Carbon::parse($validatedData['tanggal_selesai'])->setTimezone('Asia/Jakarta')->endOfDay() : null; $jobdesk = Jobdesk::create($validatedData); - // relation - $jobdesk->load('order', 'order.customer', 'user', 'order.product'); + // Load relations without role field + $jobdesk->load([ + 'order', + 'order.customer', + 'user:id,name,email', + 'order.product' + ]); return response()->json($jobdesk, 201); } catch (\Exception $e) { return response()->json(['message' => 'Server Error', 'error' => $e->getMessage()], 500); @@ -111,7 +191,12 @@ public function update(Request $request, $id) $validatedData['tanggal_selesai'] = $validatedData['tanggal_selesai'] ? Carbon::parse($validatedData['tanggal_selesai'])->setTimezone('Asia/Jakarta')->endOfDay() : null; $jobdesk->update($validatedData); - $jobdesk->load('order', 'order.customer', 'user', 'order.product'); + $jobdesk->load([ + 'order', + 'order.customer', + 'user:id,name,email', + 'order.product' + ]); return response()->json($jobdesk); } catch (\Exception $e) { return response()->json(['message' => 'Server Error', 'error' => $e->getMessage()], 500); @@ -120,7 +205,12 @@ public function update(Request $request, $id) public function show(Jobdesk $jobdesk) { - $jobdesk = Jobdesk::find($jobdesk->id)->load('order', 'order.customer', 'user', 'order.product'); + $jobdesk = Jobdesk::find($jobdesk->id)->load([ + 'order', + 'order.customer', + 'user:id,name,email', + 'order.product' + ]); return response()->json($jobdesk); } @@ -130,4 +220,279 @@ public function destroy(Jobdesk $jobdesk) $jobdesk->delete(); return response()->json(['message' => 'Jobdesk deleted successfully']); } + + /** + * Get global status counts (ignoring all filters) for dashboard stats + */ + private function getGlobalStatusCounts($user) + { + try { + // Create a fresh query without any filters + $baseQuery = Jobdesk::query(); + + // Only apply role-based filtering if user is staff + if (in_array($user->role, ['staff'])) { + $baseQuery->where('user_id', $user->id); + } + + // Get total count + $totalCount = $baseQuery->count(); + + // Count by status - handle null status gracefully + $masukCount = (clone $baseQuery)->where('status', 'Masuk')->count(); + $progressCount = (clone $baseQuery)->where('status', 'Progress')->count(); + $selesaiCount = (clone $baseQuery)->where('status', 'Selesai')->count(); + + return [ + 'total' => $totalCount, + 'masuk' => $masukCount, + 'progress' => $progressCount, + 'selesai' => $selesaiCount, + 'completion_rate' => $totalCount > 0 ? round(($selesaiCount / $totalCount) * 100, 2) : 0 + ]; + } catch (\Exception $e) { + // Return zero counts if there's an error + return [ + 'total' => 0, + 'masuk' => 0, + 'progress' => 0, + 'selesai' => 0, + 'completion_rate' => 0 + ]; + } + } + + /** + * Get status counts for dashboard stats + */ + private function getStatusCounts($query, $user) + { + try { + // Clone query for each status count to avoid conflicts + $baseQuery = clone $query; + + // Remove pagination and get total count + $totalCount = $baseQuery->count(); + + // Count by status - handle null status gracefully + $masukCount = (clone $query)->where('status', 'Masuk')->count(); + $progressCount = (clone $query)->where('status', 'Progress')->count(); + $selesaiCount = (clone $query)->where('status', 'Selesai')->count(); + + return [ + 'total' => $totalCount, + 'masuk' => $masukCount, + 'progress' => $progressCount, + 'selesai' => $selesaiCount, + 'completion_rate' => $totalCount > 0 ? round(($selesaiCount / $totalCount) * 100, 2) : 0 + ]; + } catch (\Exception $e) { + // Return zero counts if there's an error + return [ + 'total' => 0, + 'masuk' => 0, + 'progress' => 0, + 'selesai' => 0, + 'completion_rate' => 0 + ]; + } + } + + /** + * Format jobdesk response for frontend + */ + private function formatJobdeskResponse($jobdesk, $user) + { + try { + return [ + 'id' => $jobdesk->id ?? null, + 'order_id' => $jobdesk->order_id ?? null, + 'user_id' => $jobdesk->user_id ?? null, + 'description' => $jobdesk->description ?? '', + 'status' => $jobdesk->status ?? '', + 'tanggal_pengerjaan' => $jobdesk->tanggal_pengerjaan ?? null, + 'tanggal_selesai' => $jobdesk->tanggal_selesai ?? null, + 'created_at' => $jobdesk->created_at ?? null, + 'updated_at' => $jobdesk->updated_at ?? null, + + // Enhanced order information + 'order' => $jobdesk->order ? [ + 'id' => $jobdesk->order->id ?? null, + 'no_order' => $jobdesk->order->no_order ?? '', + 'order_date' => $jobdesk->order->order_date ?? null, + 'customer' => $jobdesk->order->customer ? [ + 'id' => $jobdesk->order->customer->id ?? null, + 'name' => $jobdesk->order->customer->name ?? '', + 'phone' => $jobdesk->order->customer->phone ?? '', + 'address' => $jobdesk->order->customer->address ?? '', + ] : null, + 'product' => $jobdesk->order->product ? [ + 'id' => $jobdesk->order->product->id ?? null, + 'name' => $jobdesk->order->product->name ?? '', + 'category' => $jobdesk->order->product->category ?? '', + 'description' => $jobdesk->order->product->description ?? '', + ] : null, + ] : null, + + // User information + 'user' => $jobdesk->user ? [ + 'id' => $jobdesk->user->id ?? null, + 'name' => $jobdesk->user->name ?? '', + 'email' => $jobdesk->user->email ?? '', + // Removed role field since it doesn't exist in users table + ] : null, + + // Frontend convenience fields + 'customer_name' => $jobdesk->order?->customer?->name ?? 'Tidak diketahui', + 'customer_phone' => $jobdesk->order?->customer?->phone ?? '-', + 'product_name' => $jobdesk->order?->product?->name ?? '-', + 'assigned_to' => $jobdesk->user?->name ?? 'Belum ditugaskan', + 'status_text' => $this->getStatusText($jobdesk->status ?? ''), + 'status_class' => $this->getStatusClass($jobdesk->status ?? ''), + 'is_overdue' => $this->isOverdue($jobdesk), + 'days_remaining' => $this->getDaysRemaining($jobdesk), + ]; + } catch (\Exception $e) { + // Return basic response if formatting fails + return [ + 'id' => $jobdesk->id ?? null, + 'order_id' => $jobdesk->order_id ?? null, + 'user_id' => $jobdesk->user_id ?? null, + 'description' => $jobdesk->description ?? '', + 'status' => $jobdesk->status ?? '', + 'tanggal_pengerjaan' => $jobdesk->tanggal_pengerjaan ?? null, + 'tanggal_selesai' => $jobdesk->tanggal_selesai ?? null, + 'created_at' => $jobdesk->created_at ?? null, + 'updated_at' => $jobdesk->updated_at ?? null, + 'order' => $jobdesk->order ?? null, + 'user' => $jobdesk->user ?? null, + 'customer_name' => 'Error loading data', + 'status_text' => 'Unknown', + 'formatting_error' => $e->getMessage() + ]; + } + } + + /** + * Get human readable status text + */ + private function getStatusText($status) + { + switch ($status) { + case 'Masuk': + return 'Belum Mulai'; + case 'Progress': + return 'Sedang Dikerjakan'; + case 'Selesai': + return 'Selesai'; + default: + return $status ?? 'Tidak Diketahui'; + } + } + + /** + * Get CSS class for status badge + */ + private function getStatusClass($status) + { + switch ($status) { + case 'Masuk': + return 'bg-yellow-100 text-yellow-800 border-yellow-200'; + case 'Progress': + return 'bg-blue-100 text-blue-800 border-blue-200'; + case 'Selesai': + return 'bg-green-100 text-green-800 border-green-200'; + default: + return 'bg-gray-100 text-gray-800 border-gray-200'; + } + } + + /** + * Check if jobdesk is overdue + */ + private function isOverdue($jobdesk) + { + try { + if (!$jobdesk || !$jobdesk->tanggal_selesai || $jobdesk->status === 'Selesai') { + return false; + } + + return Carbon::now()->gt(Carbon::parse($jobdesk->tanggal_selesai)); + } catch (\Exception $e) { + return false; + } + } + + /** + * Get days remaining for completion + */ + private function getDaysRemaining($jobdesk) + { + try { + if (!$jobdesk || !$jobdesk->tanggal_selesai || $jobdesk->status === 'Selesai') { + return null; + } + + $now = Carbon::now(); + $deadline = Carbon::parse($jobdesk->tanggal_selesai); + + return $now->diffInDays($deadline, false); // false = can be negative + } catch (\Exception $e) { + return null; + } + } + + /** + * Get jobdesk statistics - separate endpoint for dashboard + */ + public function stats(Request $request) + { + try { + $user = $request->user(); + + // Get global stats (ignoring filters) for dashboard + $stats = $this->getGlobalStatusCounts($user); + + // Add additional stats with error handling (also global) + try { + $baseQuery = Jobdesk::query(); + + // Only apply role-based filtering if user is staff + if (in_array($user->role, ['staff'])) { + $baseQuery->where('user_id', $user->id); + } + + $stats['overdue_count'] = (clone $baseQuery) + ->where('status', '!=', 'Selesai') + ->where('tanggal_selesai', '<', Carbon::now()) + ->whereNotNull('tanggal_selesai') + ->count(); + } catch (\Exception $e) { + $stats['overdue_count'] = 0; + } + + try { + $baseQuery = Jobdesk::query(); + + // Only apply role-based filtering if user is staff + if (in_array($user->role, ['staff'])) { + $baseQuery->where('user_id', $user->id); + } + + $stats['today_deadline'] = (clone $baseQuery) + ->where('status', '!=', 'Selesai') + ->whereDate('tanggal_selesai', Carbon::today()) + ->count(); + } catch (\Exception $e) { + $stats['today_deadline'] = 0; + } + + return response()->json($stats); + } catch (\Exception $e) { + return response()->json([ + 'message' => 'Server Error', + 'error' => $e->getMessage() + ], 500); + } + } } diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 1a1024f..70230ac 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -26,154 +26,231 @@ class OrderController extends Controller public function index(Request $request) { $customerId = $request->query('customer_id'); - $paginate = $request->query('paginate'); + $paginate = $request->query('paginate', true); $name = $request->query('name'); $productQuery = $request->query('product'); $bank = $request->query('bank'); $dari = $request->query('dari'); $sampai = $request->query('sampai'); $status = $request->query('status'); - $status = isset($status) ? $status : null; $user = $request->user(); - $query = Order::with('customer', 'customer.meta', 'jobdesks', 'product', 'product.metaProducts.meta'); + // Optimized eager loading based on frontend needs + $query = Order::with([ + 'customer:id,name,phone,address', + 'customer.meta:id,customer_id,meta_key,meta_value', + 'jobdesks:id,order_id,status,description', + 'product:id,name,category,description', + 'product.metaProducts:id,product_id,meta_id', + 'product.metaProducts.meta:id,name' + ]) + ->select([ + 'id', + 'no_order', + 'customer_id', + 'product_id', + 'order_date', + 'price', + 'payment_method', + 'paid', + 'meta', + 'lampiran', + 'created_at' + ]); + // Apply customer filter if (isset($customerId) && $customerId !== 'undefined') { $query->where('customer_id', $customerId); } - if ($name || $productQuery || $bank || $dari || $sampai) { - $query->whereHas('customer', function ($query) use ($name) { - $query->where('name', 'like', '%' . $name . '%'); + // Apply search and date filters + $this->applyFilters($query, $name, $productQuery, $bank, $dari, $sampai); + + // Apply status filter - optimized for frontend tabs + $this->applyStatusFilter($query, $status); + + $query->orderBy('created_at', 'desc'); // Changed to desc for latest first + + // Get results with or without pagination + return $this->getOrderResults($query, $paginate, $user); + } + + private function applyFilters($query, $name, $productQuery, $bank, $dari, $sampai) + { + // Search by customer name (minimum 3 characters as per frontend) + if ($name && strlen($name) >= 3) { + $query->whereHas('customer', function ($q) use ($name) { + $q->where('name', 'like', '%' . $name . '%'); }); - $query->whereHas('product', function ($query) use ($productQuery) { - $query->where('name', 'like', '%' . $productQuery . '%'); + } + + // Search by product name (minimum 3 characters as per frontend) + if ($productQuery && strlen($productQuery) >= 3) { + $query->whereHas('product', function ($q) use ($productQuery) { + $q->where('name', 'like', '%' . $productQuery . '%'); }); - if ($bank) { + } + + // Bank/category filter optimized for frontend dropdown + if ($bank) { + if ($bank === 'Perorangan') { + $query->where(function ($q) { + $q->whereHas('customer.meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank') + ->where('meta_value', 'Perorangan'); + })->orWhereDoesntHave('customer.meta', function ($subQuery) { + $subQuery->where('meta_key', 'bank'); + }); + }); + } else { $query->whereHas('customer.meta', function ($subQuery) use ($bank) { $subQuery->where('meta_key', 'bank') - ->where('meta_value', '=', $bank); + ->where('meta_value', $bank); }); } - if ($dari && $sampai) { - $query->whereBetween('order_date', [$dari, $sampai]); - } - if ($dari && !$sampai) { - $query->where('order_date', '>=', $dari); - } - if (!$dari && $sampai) { - $query->where('order_date', '<=', $sampai); - } - } else { - if ($status) { - $query->whereDoesntHave('jobdesks', function ($query) use ($status) { - $query->where('status', '!=', 'Selesai'); + } + + // Date range filter optimized for frontend date picker + if ($dari && $sampai) { + $query->whereBetween('order_date', [ + date('Y-m-d', strtotime($dari)), + date('Y-m-d', strtotime($sampai)) + ]); + } elseif ($dari) { + $query->where('order_date', '>=', date('Y-m-d', strtotime($dari))); + } elseif ($sampai) { + $query->where('order_date', '<=', date('Y-m-d', strtotime($sampai))); + } + } + + private function applyStatusFilter($query, $status) + { + if (!$status) { + return; // Show all orders by default + } + + switch ($status) { + case 'Masuk': + $query->where(function ($q) { + $q->whereHas('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->orWhereDoesntHave('jobdesks'); }); - if ($status === 'Selesai') { - $query->whereNotNull('lampiran'); - } - if ($status === 'Arsip') { - $query->whereNull('lampiran'); - } - $query->whereHas('jobdesks'); - } else if ($bank) { - if ($bank === 'Perorangan') { - $query->where(function ($q) { - $q->whereHas('customer.meta', function ($subQuery) { - $subQuery->where('meta_key', 'bank') - ->where('meta_value', 'Perorangan'); - })->orWhereDoesntHave('customer.meta', function ($subQuery) { - $subQuery->where('meta_key', 'bank'); - }); - }); - } else { - $query->whereHas('customer.meta', function ($subQuery) use ($bank) { - $subQuery->where('meta_key', 'bank') - ->where('meta_value', '=', $bank); - }); - } - } else if (!($customerId || $name)) { - $query->whereHas('jobdesks', function ($query) { + break; + + case 'Selesai': + $query->whereDoesntHave('jobdesks', function ($query) { $query->where('status', '!=', 'Selesai'); - })->orWhereDoesntHave('jobdesks'); - } + })->whereNotNull('lampiran')->whereHas('jobdesks'); + break; + + case 'Arsip': + $query->whereDoesntHave('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->whereNull('lampiran')->whereHas('jobdesks'); + break; + } + } + + private function getOrderResults($query, $paginate, $user) + { + if ($paginate === 'false' || $paginate === false) { + $orders = $query->get(); + return response()->json($orders->map(function ($order) use ($user) { + return $this->formatOrderResponse($order, $user); + })); } - $query->orderBy('created_at', 'asc'); + $orders = $query->paginate(25); + $orders->through(function ($order) use ($user) { + return $this->formatOrderResponse($order, $user); + }); + + return response()->json($orders); + } + + private function formatOrderResponse($order, $user) + { + // Calculate jobdesk count from loaded relation instead of separate query + $jobdeskCount = $order->jobdesks ? $order->jobdesks->count() : 0; + $completedJobdesks = $order->jobdesks ? $order->jobdesks->where('status', 'Selesai')->count() : 0; - // Check if pagination should be disabled - if ($paginate === 'false') { - // Get all records without pagination - $orders = $query->get()->map(function ($data) use ($user) { - $data['lampiran'] = $data->lampiran; + return [ + 'id' => $order->id, + 'no_order' => $order->no_order, + 'customer_id' => $order->customer?->id, + 'order_date' => $order->order_date, + 'product_id' => $order->product?->id, + 'price' => $user->role !== 'staff' ? $order->price : 0, + 'payment_method' => $order->payment_method, + 'paid' => $user->role !== 'staff' ? $order->paid : 0, + 'meta' => $order->meta, + 'lampiran' => $order->lampiran, + 'jobdesk_count' => $jobdeskCount, + 'completed_jobdesks' => $completedJobdesks, // Added for frontend progress calculation + 'progress_percentage' => $jobdeskCount > 0 ? round(($completedJobdesks / $jobdeskCount) * 100) : 0, + 'created_at' => $order->created_at, + 'customer' => $order->customer ? [ + 'id' => $order->customer->id, + 'name' => $order->customer->name, + 'phone' => $order->customer->phone, + 'address' => $order->customer->address, + 'meta' => $order->customer->meta ? $order->customer->meta->map(function ($meta) { + return [ + 'id' => $meta->id, + 'meta_key' => $meta->meta_key, + 'meta_value' => $meta->meta_value + ]; + }) : [] + ] : null, + 'jobdesks' => $order->jobdesks ? $order->jobdesks->map(function ($jobdesk) { return [ - 'id' => $data->id, - 'no_order' => $data->no_order, - 'customer_id' => $data->customer->id ?? null, - 'order_date' => $data->order_date, - 'product_id' => $data->product->id ?? null, - 'price' => $user->role !== 'staff' ? $data->price : 0, - 'payment_method' => $data->payment_method, - 'paid' => $user->role !== 'staff' ? $data->paid : 0, - 'meta' => $data->meta, - 'lampiran' => $data->lampiran, - 'jobdesk_count' => $data->jobdesks()->count(), - 'created_at' => $data->created_at, - 'customer' => [ - 'id' => $data->customer->id, - 'name' => $data->customer->name, - 'phone' => $data->customer->phone, - 'address' => $data->customer->address, - 'meta' => $data->customer->meta - ], - 'jobdesks' => $data->jobdesks, - 'product' => [ - 'id' => $data->product->id, - 'name' => $data->product->name, - 'category' => $data->product->category, - 'description' => $data->product->description, - 'meta_products' => $data->product->metaProducts->pluck('meta'), - ] + 'id' => $jobdesk->id, + 'status' => $jobdesk->status, + 'description' => $jobdesk->description ?? '-' ]; - }); - } else { - // Paginate results - $orders = $query->paginate(25); - $orders->getCollection()->transform(function ($data) use ($user) { - $data['lampiran'] = $data->lampiran; + }) : [], + 'product' => $order->product ? [ + 'id' => $order->product->id, + 'name' => $order->product->name, + 'category' => $order->product->category, + 'description' => $order->product->description, + 'meta_products' => $order->product->metaProducts ? $order->product->metaProducts->map(function ($metaProduct) { + return $metaProduct->meta ? [ + 'id' => $metaProduct->meta->id, + 'name' => $metaProduct->meta->name + ] : null; + })->filter() : [], + ] : null, + 'role' => $user->role, + // Added fields for frontend convenience + 'is_completed' => $jobdeskCount > 0 && $completedJobdesks === $jobdeskCount, + 'has_lampiran' => !empty($order->lampiran), + 'last_jobdesk_status' => $order->jobdesks && $order->jobdesks->isNotEmpty() + ? $this->getLastJobdeskStatus($order->jobdesks) + : null, + ]; + } + + private function getLastJobdeskStatus($jobdesks) + { + // Priority order as per frontend logic + $priority = ['Progress', 'Masuk', 'Selesai']; + + foreach ($priority as $status) { + $lastJobdesk = $jobdesks->where('status', $status)->last(); + if ($lastJobdesk) { return [ - 'id' => $data->id, - 'no_order' => $data->no_order, - 'customer_id' => $data->customer->id ?? null, - 'order_date' => $data->order_date, - 'product_id' => $data->product->id ?? null, - 'price' => $user->role !== 'staff' ? $data->price : 0, - 'payment_method' => $data->payment_method, - 'paid' => $user->role !== 'staff' ? $data->paid : 0, - 'meta' => $data->meta, - 'lampiran' => $data->lampiran, - 'jobdesk_count' => $data->jobdesks()->count(), - 'created_at' => $data->created_at, - 'customer' => $data->customer ? [ - 'id' => $data->customer->id, - 'name' => $data->customer->name, - 'phone' => $data->customer->phone, - 'address' => $data->customer->address, - 'meta' => $data->customer->meta - ] : null, - 'jobdesks' => $data->jobdesks, - 'product' => $data->product ? [ - 'id' => $data->product->id, - 'name' => $data->product->name, - 'category' => $data->product->category, - 'description' => $data->product->description, - 'meta_products' => $data->product->metaProducts->pluck('meta'), - ] : null, - 'role' => $user->role, + 'status' => $status, + 'description' => $lastJobdesk->description ?? '-' ]; - }); + } } - return response()->json($orders); + + return [ + 'status' => null, + 'description' => '-' + ]; } public function show(Order $order) @@ -329,4 +406,43 @@ public function destroy(Order $order) $order->delete(); return response()->json($order); } + + /** + * Get order statistics for dashboard + */ + public function stats(Request $request) + { + $customerId = $request->query('customer_id'); + + $query = Order::query(); + + if (isset($customerId) && $customerId !== 'undefined') { + $query->where('customer_id', $customerId); + } + + $totalOrders = $query->count(); + + // Count orders by status based on jobdesk completion + $masukCount = (clone $query)->where(function ($q) { + $q->whereHas('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->orWhereDoesntHave('jobdesks'); + })->count(); + + $selesaiCount = (clone $query)->whereDoesntHave('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->whereNotNull('lampiran')->whereHas('jobdesks')->count(); + + $arsipCount = (clone $query)->whereDoesntHave('jobdesks', function ($query) { + $query->where('status', '!=', 'Selesai'); + })->whereNull('lampiran')->whereHas('jobdesks')->count(); + + return response()->json([ + 'total_orders' => $totalOrders, + 'masuk' => $masukCount, + 'selesai' => $selesaiCount, + 'arsip' => $arsipCount, + 'completion_rate' => $totalOrders > 0 ? round((($selesaiCount + $arsipCount) / $totalOrders) * 100, 2) : 0 + ]); + } } diff --git a/routes/api.php b/routes/api.php index d0dd87d..ed92279 100644 --- a/routes/api.php +++ b/routes/api.php @@ -75,6 +75,12 @@ Route::post('customers/{customer}/meta', [CustomerController::class, 'storeMeta']); + // Order stats endpoint + Route::get('orders/stats', [OrderController::class, 'stats']); + + // Jobdesk stats endpoint + Route::get('jobdesks/stats', [JobdeskController::class, 'stats']); + // API Resources Route::apiResources([ 'posts' => PostController::class, From 993b62ed3478685cf8b0c1ac00d07da6ca0fd947 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 27 Jul 2025 19:03:08 +0700 Subject: [PATCH 172/184] add seeder notification --- database/seeders/DatabaseSeeder.php | 5 + database/seeders/NotificationSeeder.php | 175 ++++++++++++++++++ database/seeders/README_NotificationSeeder.md | 97 ++++++++++ 3 files changed, 277 insertions(+) create mode 100644 database/seeders/NotificationSeeder.php create mode 100644 database/seeders/README_NotificationSeeder.md diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index fa83c9c..328c187 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -41,5 +41,10 @@ public function run(): void ]); } } + + // Seed notifications (after users, customers, and orders are created) + $this->call([ + NotificationSeeder::class, + ]); } } diff --git a/database/seeders/NotificationSeeder.php b/database/seeders/NotificationSeeder.php new file mode 100644 index 0000000..a9f9a86 --- /dev/null +++ b/database/seeders/NotificationSeeder.php @@ -0,0 +1,175 @@ +truncate(); + + // Ambil sample users dan orders + $users = User::take(5)->get(); + $orders = Order::take(10)->get(); + + if ($users->isEmpty() || $orders->isEmpty()) { + $this->command->warn('Tidak ada user atau order untuk membuat notifikasi. Jalankan UserSeeder dan OrderSeeder terlebih dahulu.'); + return; + } + + $notifications = []; + $now = Carbon::now(); + + // Template notifikasi untuk berbagai jenis + $notificationTemplates = [ + // New Order Notifications + [ + 'type' => 'App\Notifications\NewOrderNotification', + 'data' => [ + 'title' => 'Order Baru Masuk', + 'message' => 'Ada order baru yang perlu ditangani', + 'order_id' => null, // akan diisi dinamis + 'order_no' => null, // akan diisi dinamis + 'customer_name' => null, // akan diisi dinamis + 'action_url' => '/orders/', + 'icon' => 'bell', + 'type' => 'new_order' + ] + ], + // Pending Jobdesk Notifications + [ + 'type' => 'App\Notifications\PendingJobdesk', + 'data' => [ + 'title' => 'Tugas Menunggu Dikerjakan', + 'message' => 'Ada tugas yang belum dikerjakan dan mendekati deadline', + 'jobdesk_id' => null, // akan diisi dinamis + 'order_id' => null, // akan diisi dinamis + 'deadline' => null, // akan diisi dinamis + 'action_url' => '/jobdesk/', + 'icon' => 'clock', + 'type' => 'pending_jobdesk' + ] + ], + // System Notifications + [ + 'type' => 'App\Notifications\SystemNotification', + 'data' => [ + 'title' => 'Selamat Datang di Sistem', + 'message' => 'Akun Anda telah berhasil dibuat dan diaktifkan', + 'action_url' => '/dashboard', + 'icon' => 'user-check', + 'type' => 'welcome' + ] + ], + [ + 'type' => 'App\Notifications\SystemNotification', + 'data' => [ + 'title' => 'Backup Database Berhasil', + 'message' => 'Backup database harian telah berhasil dilakukan', + 'action_url' => '/settings', + 'icon' => 'database', + 'type' => 'backup_success' + ] + ], + [ + 'type' => 'App\Notifications\SystemNotification', + 'data' => [ + 'title' => 'Update Sistem Tersedia', + 'message' => 'Ada update sistem terbaru yang tersedia untuk diinstall', + 'action_url' => '/system/updates', + 'icon' => 'download', + 'type' => 'system_update' + ] + ] + ]; + + // Buat notifikasi untuk setiap user + foreach ($users as $user) { + // Buat 3-5 notifikasi per user + $notificationCount = rand(3, 5); + + for ($i = 0; $i < $notificationCount; $i++) { + $template = $notificationTemplates[array_rand($notificationTemplates)]; + $order = $orders->random(); + + // Sesuaikan data berdasarkan jenis notifikasi + $data = $template['data']; + + if ($template['type'] === 'App\Notifications\NewOrderNotification') { + $data['order_id'] = $order->id; + $data['order_no'] = $order->no_order; + $data['customer_name'] = $order->customer->name ?? 'Customer'; + $data['action_url'] = '/orders/' . $order->id; + } elseif ($template['type'] === 'App\Notifications\PendingJobdesk') { + $data['order_id'] = $order->id; + $data['jobdesk_id'] = rand(1, 50); // Random jobdesk ID + $data['deadline'] = $now->copy()->addDays(rand(1, 7))->format('Y-m-d H:i:s'); + $data['action_url'] = '/jobdesk/' . $data['jobdesk_id']; + } + + // Tentukan status read/unread (80% unread, 20% read) + $isRead = rand(1, 100) <= 20; + + $notifications[] = [ + 'id' => \Illuminate\Support\Str::uuid(), + 'type' => $template['type'], + 'notifiable_type' => 'App\Models\User', + 'notifiable_id' => $user->id, + 'data' => json_encode($data), + 'read_at' => $isRead ? $now->copy()->subDays(rand(1, 30))->format('Y-m-d H:i:s') : null, + 'created_at' => $now->copy()->subDays(rand(0, 30))->subHours(rand(0, 23))->format('Y-m-d H:i:s'), + 'updated_at' => $now->format('Y-m-d H:i:s'), + ]; + } + } + + // Tambahkan beberapa notifikasi broadcast untuk semua user + $broadcastNotifications = [ + [ + 'title' => 'Maintenance Sistem Terjadwal', + 'message' => 'Sistem akan menjalani maintenance pada hari Minggu jam 02:00 - 04:00 WIB', + 'icon' => 'tools', + 'type' => 'maintenance', + 'action_url' => '/announcements' + ], + [ + 'title' => 'Pelatihan Sistem Baru', + 'message' => 'Akan ada pelatihan penggunaan fitur baru sistem pada hari Jumat', + 'icon' => 'graduation-cap', + 'type' => 'training', + 'action_url' => '/training' + ] + ]; + + foreach ($broadcastNotifications as $broadcast) { + foreach ($users as $user) { + $notifications[] = [ + 'id' => \Illuminate\Support\Str::uuid(), + 'type' => 'App\Notifications\SystemNotification', + 'notifiable_type' => 'App\Models\User', + 'notifiable_id' => $user->id, + 'data' => json_encode($broadcast), + 'read_at' => rand(1, 100) <= 30 ? $now->copy()->subDays(rand(1, 5))->format('Y-m-d H:i:s') : null, + 'created_at' => $now->copy()->subDays(rand(1, 7))->format('Y-m-d H:i:s'), + 'updated_at' => $now->format('Y-m-d H:i:s'), + ]; + } + } + + // Insert semua notifikasi ke database + DB::table('notifications')->insert($notifications); + + $this->command->info('Berhasil membuat ' . count($notifications) . ' notifikasi untuk ' . $users->count() . ' user'); + } +} diff --git a/database/seeders/README_NotificationSeeder.md b/database/seeders/README_NotificationSeeder.md new file mode 100644 index 0000000..7616a77 --- /dev/null +++ b/database/seeders/README_NotificationSeeder.md @@ -0,0 +1,97 @@ +# Notification Seeder Documentation + +## File yang Dibuat + +### 1. NotificationSeeder.php + +- **Lokasi**: `database/seeders/NotificationSeeder.php` +- **Fungsi**: Membuat data dummy notifikasi untuk testing dan development + +## Fitur NotificationSeeder + +### Jenis Notifikasi yang Dibuat: + +1. **New Order Notification** (`App\Notifications\NewOrderNotification`) + + - Notifikasi order baru masuk + - Data: order_id, order_no, customer_name, action_url + +2. **Pending Jobdesk** (`App\Notifications\PendingJobdesk`) + + - Notifikasi tugas yang pending/mendekati deadline + - Data: jobdesk_id, order_id, deadline, action_url + +3. **System Notification** (`App\Notifications\SystemNotification`) + - Welcome message + - Backup database berhasil + - Update sistem tersedia + - Maintenance terjadwal + - Pelatihan sistem + +### Karakteristik Data: + +- **Jumlah**: 3-5 notifikasi per user + 2 broadcast notification untuk semua user +- **Status Read**: 20% sudah dibaca, 80% belum dibaca (realistic scenario) +- **Tanggal**: Random dalam 30 hari terakhir +- **UUID**: Menggunakan UUID untuk primary key +- **JSON Data**: Data notifikasi disimpan dalam format JSON + +### Struktur Data Notifikasi: + +```json +{ + "title": "Judul Notifikasi", + "message": "Pesan notifikasi", + "action_url": "/path/to/action", + "icon": "icon-name", + "type": "notification_type", + "order_id": 123, + "customer_name": "Nama Customer" +} +``` + +## Cara Penggunaan + +### Jalankan Seeder Individual: + +```bash +php artisan db:seed --class=NotificationSeeder +``` + +### Jalankan Semua Seeder (termasuk NotificationSeeder): + +```bash +php artisan db:seed +``` + +### Reset dan Seed Ulang: + +```bash +php artisan migrate:fresh --seed +``` + +## Statistik Hasil Seeder + +Berdasarkan hasil terakhir: + +- **Total notifikasi**: 29 +- **Belum dibaca**: 24 (83%) +- **Sudah dibaca**: 5 (17%) + +## Dependencies + +Seeder ini membutuhkan: + +- User model dengan data user +- Order model dengan data order dan customer +- Tabel notifications (migrasi sudah ada) + +## Integration dengan DatabaseSeeder + +NotificationSeeder sudah ditambahkan ke `DatabaseSeeder.php` dan akan dijalankan setelah: + +- Users dibuat +- Customers dan Orders dibuat +- Semua data master sudah tersedia + +Hal ini memastikan referensi data (user_id, order_id) valid saat membuat notifikasi. From ef763ba91a5a3b3a60fe7785791323775709a156 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sun, 27 Jul 2025 20:03:22 +0700 Subject: [PATCH 173/184] update setting controller --- app/Http/Controllers/SettingController.php | 66 +++++++++++++++++++ .../Controllers/SettingLoginController.php | 44 +++++++++---- 2 files changed, 96 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/SettingController.php b/app/Http/Controllers/SettingController.php index e914d6a..464e5b5 100644 --- a/app/Http/Controllers/SettingController.php +++ b/app/Http/Controllers/SettingController.php @@ -94,6 +94,67 @@ public function destroy($key) return $this->responseSuccess('Setting deleted successfully.'); } + /** + * Get background settings specifically + */ + public function getBackground() + { + $backgroundSettings = Setting::whereIn('setting_key', ['background_color', 'background_image', 'login_style']) + ->pluck('setting_value', 'setting_key') + ->toArray(); + + return response()->json([ + 'color' => $backgroundSettings['background_color'] ?? '', + 'image' => $backgroundSettings['background_image'] ? asset('storage/' . $backgroundSettings['background_image']) : null, + 'style' => $backgroundSettings['login_style'] ?? 'center' + ]); + } + + /** + * Store background settings specifically + */ + public function storeBackground(Request $request) + { + $validatedData = $request->validate([ + 'color' => 'nullable|string|max:50', + 'style' => 'nullable|string|in:center,side', + 'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:1024', // 1MB max + ]); + + $settings = []; + + // Handle color + if (isset($validatedData['color'])) { + $settings['background_color'] = $validatedData['color']; + } + + // Handle style + if (isset($validatedData['style'])) { + $settings['login_style'] = $validatedData['style']; + } + + // Handle image upload + if ($request->hasFile('image')) { + // Delete old image if exists + $oldImageSetting = Setting::where('setting_key', 'background_image')->first(); + if ($oldImageSetting && $oldImageSetting->setting_value) { + Storage::disk('public')->delete($oldImageSetting->setting_value); + } + + $imagePath = $request->file('image')->store('backgrounds', 'public'); + $settings['background_image'] = $imagePath; + } + + // Save settings + $this->saveSettings($settings); + + return $this->responseSuccess('Background settings saved successfully.', [ + 'color' => $settings['background_color'] ?? '', + 'image' => isset($settings['background_image']) ? asset('storage/' . $settings['background_image']) : null, + 'style' => $settings['login_style'] ?? 'center' + ]); + } + /** * Validation rules for storing/updating settings. */ @@ -111,6 +172,11 @@ protected function validationRules() 'new_order' => 'nullable|string', 'project_assignment' => 'nullable|string', 'followup_project' => 'nullable|string', + + // Background/Login settings + 'color' => 'nullable|string|max:50', + 'style' => 'nullable|string|max:50', + 'image' => 'nullable|image|mimes:jpeg,png,jpg,webp|max:1024', // 1MB max ]; } diff --git a/app/Http/Controllers/SettingLoginController.php b/app/Http/Controllers/SettingLoginController.php index f545734..5f0c9c8 100644 --- a/app/Http/Controllers/SettingLoginController.php +++ b/app/Http/Controllers/SettingLoginController.php @@ -15,10 +15,11 @@ public function index() { $setting = Setting::where('setting_key', 'background')->first(); $background = $setting ? json_decode($setting->setting_value, true) : []; + return response()->json([ - 'color' => $background['color'] ?? 'rgba(0, 0, 0, 0.1)', - 'image' => $background['image'] ?? asset('assets/bg.jpeg'), - 'style' => $background['style'] ?? null + 'color' => $background['color'] ?? '#ffffff', + 'image' => $background['image'] ?? null, + 'style' => $background['style'] ?? 'center' ]); } @@ -28,9 +29,9 @@ public function index() public function store(Request $request) { $validatedData = $request->validate([ - 'color' => 'nullable|string|max:7', // Format hex warna (#FFFFFF) - 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', // Maksimal 2MB - 'style' => 'nullable|string', + 'color' => 'nullable|string|max:50', // Lebih fleksibel untuk hex, rgba, dll + 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif,webp|max:1024', // Maksimal 1MB, tambah webp + 'style' => 'nullable|string|in:center,side', ]); $background = []; @@ -45,14 +46,18 @@ public function store(Request $request) $background['style'] = $request->input('style'); } - //hapus gambar lama dari storage + // Hapus gambar lama dari storage jika ada gambar baru if ($request->hasFile('image') && $request->file('image')->isValid()) { $oldImage = Setting::where('setting_key', 'background')->first(); if ($oldImage) { - $oldImagePath = $oldImage->setting_value; - if (isset($oldImagePath['image'])) { - $oldImage = $oldImagePath['image']; - Storage::disk('public')->delete($oldImage); + $oldImageData = json_decode($oldImage->setting_value, true); + if (isset($oldImageData['image'])) { + // Extract path dari URL untuk menghapus file + $oldImageUrl = $oldImageData['image']; + $oldImagePath = str_replace(asset('storage/'), '', $oldImageUrl); + if ($oldImagePath !== $oldImageUrl) { // Pastikan ini file dari storage + Storage::disk('public')->delete($oldImagePath); + } } } @@ -60,10 +65,13 @@ public function store(Request $request) $background['image'] = asset('storage/' . $imagePath); } - // jika tidak ada gambar baru, gunakan gambar lama + // Jika tidak ada gambar baru, gunakan gambar lama if (!isset($background['image'])) { $oldImage = Setting::where('setting_key', 'background')->first(); - $background['image'] = $oldImage ? json_decode($oldImage->setting_value, true)['image'] : null; + if ($oldImage) { + $oldImageData = json_decode($oldImage->setting_value, true); + $background['image'] = $oldImageData['image'] ?? null; + } } // Simpan ke database @@ -72,7 +80,15 @@ public function store(Request $request) ['setting_value' => json_encode($background)], ); - return response()->json(['message' => 'Pengaturan latar belakang berhasil disimpan.']); + return response()->json([ + 'success' => true, + 'message' => 'Pengaturan latar belakang berhasil disimpan.', + 'data' => [ + 'color' => $background['color'] ?? '', + 'image' => $background['image'] ?? null, + 'style' => $background['style'] ?? 'center' + ] + ]); } /** From 6a2be25d65d166eb2c48c4facadc8d1bb008aad1 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 7 Aug 2025 20:52:48 +0700 Subject: [PATCH 174/184] add email notifications --- .../Requests/Auth/ProfileUpdateRequest.php | 13 +++++++++ app/Models/User.php | 2 ++ app/Notifications/NewOrderNotification.php | 9 +++++- app/Notifications/PendingJobdesk.php | 9 +++++- ...add_email_notifications_to_users_table.php | 28 +++++++++++++++++++ 5 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 database/migrations/2025_08_07_204447_add_email_notifications_to_users_table.php diff --git a/app/Http/Requests/Auth/ProfileUpdateRequest.php b/app/Http/Requests/Auth/ProfileUpdateRequest.php index b52407f..58e8196 100644 --- a/app/Http/Requests/Auth/ProfileUpdateRequest.php +++ b/app/Http/Requests/Auth/ProfileUpdateRequest.php @@ -36,6 +36,7 @@ public function rules(): array 'role' => ['nullable', 'string'], 'password' => ['nullable', 'string', 'min:8', 'confirmed'], 'avatar' => ['nullable'], + 'email_notifications' => ['boolean'], ]; if (is_string($this->avatar)) { @@ -46,4 +47,16 @@ public function rules(): array return $rules; } + + /** + * Prepare the data for validation. + */ + protected function prepareForValidation() + { + if ($this->has('email_notifications')) { + $this->merge([ + 'email_notifications' => filter_var($this->email_notifications, FILTER_VALIDATE_BOOLEAN), + ]); + } + } } diff --git a/app/Models/User.php b/app/Models/User.php index 05d3699..12d7126 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -27,6 +27,7 @@ class User extends Authenticatable 'phone', 'address', 'is_admin', + 'email_notifications', ]; /** @@ -49,6 +50,7 @@ protected function casts(): array return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', + 'email_notifications' => 'boolean', ]; } diff --git a/app/Notifications/NewOrderNotification.php b/app/Notifications/NewOrderNotification.php index 5a52a41..e2a0d39 100644 --- a/app/Notifications/NewOrderNotification.php +++ b/app/Notifications/NewOrderNotification.php @@ -51,7 +51,14 @@ public function __construct($order) */ public function via($notifiable) { - return ['database']; //'mail', 'database' + $channels = ['database']; + + // Hanya kirim email jika user mengaktifkan notifikasi email + if ($notifiable->email_notifications ?? true) { + $channels[] = 'mail'; + } + + return $channels; } /** diff --git a/app/Notifications/PendingJobdesk.php b/app/Notifications/PendingJobdesk.php index c3a1bae..cff2f36 100644 --- a/app/Notifications/PendingJobdesk.php +++ b/app/Notifications/PendingJobdesk.php @@ -42,7 +42,14 @@ public function __construct($data) */ public function via($notifiable) { - return ['mail', 'database']; //'mail', 'database' + $channels = ['database']; + + // Hanya kirim email jika user mengaktifkan notifikasi email + if ($notifiable->email_notifications ?? true) { + $channels[] = 'mail'; + } + + return $channels; } /** diff --git a/database/migrations/2025_08_07_204447_add_email_notifications_to_users_table.php b/database/migrations/2025_08_07_204447_add_email_notifications_to_users_table.php new file mode 100644 index 0000000..3f002be --- /dev/null +++ b/database/migrations/2025_08_07_204447_add_email_notifications_to_users_table.php @@ -0,0 +1,28 @@ +boolean('email_notifications')->default(true)->after('email_verified_at'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('email_notifications'); + }); + } +}; From 08dafffe4d567ea0d6f4f238b201ccd415557869 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 7 Aug 2025 22:38:15 +0700 Subject: [PATCH 175/184] add data customer in relation with order --- app/Http/Controllers/CustomerController.php | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/CustomerController.php b/app/Http/Controllers/CustomerController.php index 55d65b3..c4a28bd 100644 --- a/app/Http/Controllers/CustomerController.php +++ b/app/Http/Controllers/CustomerController.php @@ -159,8 +159,22 @@ public function store(Request $request) */ public function show(Customer $customer) { - $customer = Customer::find($customer->id); - return response()->json($customer); + $customer = Customer::with('orders.jobdesks', 'meta')->find($customer->id); + + $response = [ + 'id' => $customer->id, + 'name' => $customer->name, + 'phone' => $customer->phone, + 'email' => $customer->email, + 'address' => $customer->address, + 'order_count' => $customer->orders->count(), + 'orders' => $customer->orders, + 'meta' => $customer->meta, + 'created_at' => $customer->created_at, + 'updated_at' => $customer->updated_at + ]; + + return response()->json($response); } /** From 0262bfee6f38f0f4dc821c9d70913147b59fabcb Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 19 Aug 2025 15:56:35 +0700 Subject: [PATCH 176/184] perbaikan konfirmasi hapus jobdesk --- app/Http/Controllers/JobdeskController.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index d5b8731..2668f05 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -216,9 +216,15 @@ public function show(Jobdesk $jobdesk) public function destroy(Jobdesk $jobdesk) { - $jobdesk = Jobdesk::find($jobdesk->id); - $jobdesk->delete(); - return response()->json(['message' => 'Jobdesk deleted successfully']); + try { + $jobdesk->delete(); + return response()->json(['message' => 'Jobdesk deleted successfully']); + } catch (\Exception $e) { + return response()->json([ + 'message' => 'Error deleting jobdesk', + 'error' => $e->getMessage() + ], 500); + } } /** From b427e01f29ac9436943a0d7935a80b92552ada55 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 19 Aug 2025 16:55:30 +0700 Subject: [PATCH 177/184] perbaikan pagination jobdesk --- app/Http/Controllers/JobdeskController.php | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/app/Http/Controllers/JobdeskController.php b/app/Http/Controllers/JobdeskController.php index 2668f05..7238b79 100644 --- a/app/Http/Controllers/JobdeskController.php +++ b/app/Http/Controllers/JobdeskController.php @@ -124,19 +124,9 @@ public function index(Request $request) } }); - // Add meta information for frontend - $response = $jobdesks->toArray(); - $response['status_counts'] = $totalCounts; - $response['current_filter'] = [ - 'status' => $status, - 'order_id' => $orderId, - 'user_id' => $userId, - 'name' => $name, - 'dari' => $dari, - 'sampai' => $sampai - ]; - - return response()->json($response); + // Just return the paginated jobdesks like OrderController + // We'll add the extra data in the frontend from status_counts endpoint + return response()->json($jobdesks); } catch (\Exception $e) { return response()->json([ 'message' => 'Server Error', From c3d739f0c51b0fc356e46e523fb962316b799602 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 19 Aug 2025 17:02:41 +0700 Subject: [PATCH 178/184] change default order --- app/Http/Controllers/OrderController.php | 26 +++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index 70230ac..faf2850 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -69,7 +69,31 @@ public function index(Request $request) // Apply status filter - optimized for frontend tabs $this->applyStatusFilter($query, $status); - $query->orderBy('created_at', 'desc'); // Changed to desc for latest first + // Default behavior: show oldest unfinished orders first, then newest finished orders + if (!$status) { + // When no status filter is applied, prioritize unfinished orders (oldest first) + $query->orderBy( + \DB::raw("CASE + WHEN ( + SELECT COUNT(*) + FROM jobdesks + WHERE jobdesks.order_id = orders.id + AND jobdesks.status != 'Selesai' + ) > 0 + OR ( + SELECT COUNT(*) + FROM jobdesks + WHERE jobdesks.order_id = orders.id + ) = 0 + THEN 0 + ELSE 1 + END") + ) + ->orderBy('created_at', 'asc'); // Oldest unfinished first + } else { + // When status filter is applied, use latest first + $query->orderBy('created_at', 'desc'); + } // Get results with or without pagination return $this->getOrderResults($query, $paginate, $user); From 3a56da5dab992ccc488802932aed3021ba63e05a Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 2 Sep 2025 13:15:56 +0700 Subject: [PATCH 179/184] include type data --- app/Http/Controllers/OrderController.php | 5 +++-- app/Models/Product.php | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/OrderController.php b/app/Http/Controllers/OrderController.php index faf2850..194f0cb 100644 --- a/app/Http/Controllers/OrderController.php +++ b/app/Http/Controllers/OrderController.php @@ -42,7 +42,7 @@ public function index(Request $request) 'jobdesks:id,order_id,status,description', 'product:id,name,category,description', 'product.metaProducts:id,product_id,meta_id', - 'product.metaProducts.meta:id,name' + 'product.metaProducts.meta:id,name,type' ]) ->select([ 'id', @@ -242,7 +242,8 @@ private function formatOrderResponse($order, $user) 'meta_products' => $order->product->metaProducts ? $order->product->metaProducts->map(function ($metaProduct) { return $metaProduct->meta ? [ 'id' => $metaProduct->meta->id, - 'name' => $metaProduct->meta->name + 'name' => $metaProduct->meta->name, + 'type' => $metaProduct->meta->type ] : null; })->filter() : [], ] : null, diff --git a/app/Models/Product.php b/app/Models/Product.php index 070b6ed..55220e1 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -20,6 +20,13 @@ public function metaProducts() return $this->hasMany(MetaProduct::class, 'product_id'); } + // Relationship to get metas through pivot table with meta details + public function metas() + { + return $this->belongsToMany(Meta::class, 'meta_product', 'product_id', 'meta_id') + ->select(['metas.id', 'metas.name', 'metas.type']); + } + public function orders() { return $this->hasMany(Order::class); From f85d2db08aa0fcae4509b080fde09bf760875bb8 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Thu, 18 Sep 2025 23:07:47 +0700 Subject: [PATCH 180/184] feat(DashboardController): add date range filtering for dashboard metrics Implement date range filtering for all dashboard metrics to allow users to view data for custom periods. Defaults to current month if no dates are provided. Includes comparison with previous period for revenue metrics. --- app/Http/Controllers/DashboardController.php | 41 +++++++++++++++----- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 8617233..bf81e20 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -17,20 +17,43 @@ class DashboardController extends Controller public function index(Request $request) { $user = $request->user(); + + // Get date filters from request + $dateFrom = $request->get('date_from'); + $dateTo = $request->get('date_to'); + + // If no dates provided, use current month as default + if (!$dateFrom || !$dateTo) { + $dateFrom = now()->startOfMonth()->format('Y-m-d'); + $dateTo = now()->format('Y-m-d'); + } + + // Base queries with date filters + $orderQuery = Order::whereBetween('order_date', [$dateFrom, $dateTo]); + $jobdeskQuery = Jobdesk::whereBetween('created_at', [$dateFrom . ' 00:00:00', $dateTo . ' 23:59:59']); + + // Total counts (not filtered by date for context) $totalCustomers = Customer::count(); $totalOrders = Order::count(); - $orderBulanIni = Order::whereMonth('order_date', now()->month)->count(); $totalKaryawan = User::count(); - $totalPendapatan = intval(Order::sum('paid')); - $pendapatanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('paid')); - $pendapatanBulanSebelumnya = intval(Order::whereMonth('order_date', now()->subMonth()->month)->sum('paid')); - $totalTagihan = intval(Order::sum('price')) - $totalPendapatan; - $totalTagihanBulanIni = intval(Order::whereMonth('order_date', now()->month)->sum('price')); - $totalBelumbayar = $totalTagihan - $totalPendapatan; + // Filtered data based on date range + $orderBulanIni = $orderQuery->count(); + $totalPendapatan = intval($orderQuery->sum('paid')); + $pendapatanBulanIni = intval($orderQuery->sum('paid')); + + // Previous period comparison (same date range but previous period) + $dateDiff = \Carbon\Carbon::parse($dateFrom)->diffInDays(\Carbon\Carbon::parse($dateTo)); + $previousDateFrom = \Carbon\Carbon::parse($dateFrom)->subDays($dateDiff + 1)->format('Y-m-d'); + $previousDateTo = \Carbon\Carbon::parse($dateFrom)->subDay()->format('Y-m-d'); + $pendapatanBulanSebelumnya = intval(Order::whereBetween('order_date', [$previousDateFrom, $previousDateTo])->sum('paid')); + + $totalTagihanPeriode = intval($orderQuery->sum('price')); + $totalTagihanBulanIni = $totalTagihanPeriode; + $totalTagihan = intval(Order::sum('price')) - intval(Order::sum('paid')); - // Menghitung jobdesk berdasarkan status - $totalJobdesk = Jobdesk::select('status', DB::raw('count(*) as count')) + // Menghitung jobdesk berdasarkan status dengan filter tanggal + $totalJobdesk = $jobdeskQuery->select('status', DB::raw('count(*) as count')) ->groupBy('status') ->pluck('count', 'status'); From eaa19e7c25ca022aaa2eac2c74b9efc1a747cc3d Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Fri, 19 Sep 2025 00:36:45 +0700 Subject: [PATCH 181/184] build: add tailwindcss dependency and bump version to 1.0.1 --- package-lock.json | 13 ++++++++++--- package.json | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index cbf842d..a4b203f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,16 @@ { "name": "larapi", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "larapi", - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "archiver": "^5.3.1", - "fs": "0.0.1-security" + "fs": "0.0.1-security", + "tailwindcss": "^4.1.13" } }, "node_modules/archiver": { @@ -506,6 +507,12 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/tailwindcss": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", + "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", + "license": "MIT" + }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", diff --git a/package.json b/package.json index 0485543..504d803 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "archiver": "^5.3.1", - "fs": "0.0.1-security" + "fs": "0.0.1-security", + "tailwindcss": "^4.1.13" } } From f0015655cf6bfa0578a13d7687295a2763bfbb39 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Sat, 20 Sep 2025 22:24:53 +0700 Subject: [PATCH 182/184] feat(DashboardController): add 30-day jobdesk trend data Add functionality to track and display jobdesk status trends over the last 30 days in the dashboard response --- app/Http/Controllers/DashboardController.php | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index bf81e20..b577bda 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -57,6 +57,53 @@ public function index(Request $request) ->groupBy('status') ->pluck('count', 'status'); + // Data tren jobdesk 30 hari terakhir + $thirtyDaysAgo = now()->subDays(30)->format('Y-m-d'); + $today = now()->format('Y-m-d'); + + $jobdeskTrend = []; + for ($i = 29; $i >= 0; $i--) { + $date = now()->subDays($i)->format('Y-m-d'); + $dateStart = $date . ' 00:00:00'; + $dateEnd = $date . ' 23:59:59'; + + $dailyJobdesk = Jobdesk::whereBetween('created_at', [$dateStart, $dateEnd]) + ->select('status', DB::raw('count(*) as count')) + ->groupBy('status') + ->pluck('count', 'status'); + + $jobdeskTrend[] = [ + 'date' => $date, + 'masuk' => (int) $dailyJobdesk->get('Masuk', 0), + 'progress' => (int) $dailyJobdesk->get('Progress', 0), + 'selesai' => (int) $dailyJobdesk->get('Selesai', 0), + ]; + } + + // Data tren pendapatan dan tagihan 12 bulan terakhir + $monthlyTrend = []; + for ($i = 11; $i >= 0; $i--) { + $monthStart = now()->subMonths($i)->startOfMonth(); + $monthEnd = now()->subMonths($i)->endOfMonth(); + + $monthlyRevenue = Order::whereBetween('order_date', [ + $monthStart->format('Y-m-d'), + $monthEnd->format('Y-m-d') + ])->sum('paid'); + + $monthlyBilling = Order::whereBetween('order_date', [ + $monthStart->format('Y-m-d'), + $monthEnd->format('Y-m-d') + ])->sum('price'); + + $monthlyTrend[] = [ + 'month' => $monthStart->format('Y-m'), + 'month_name' => $monthStart->translatedFormat('M'), + 'revenue' => (int) $monthlyRevenue, + 'billing' => (int) $monthlyBilling, + ]; + } + // Menyiapkan data untuk response $data = [ 'total_customers' => $totalCustomers, @@ -73,6 +120,8 @@ public function index(Request $request) 'Progress' => (int) $totalJobdesk->get('Progress', 0), 'Selesai' => (int) $totalJobdesk->get('Selesai', 0), ], + 'jobdesk_trend' => $jobdeskTrend, + 'monthly_trend' => $monthlyTrend, ]; return response()->json($data); From c7f0bb9fd080534baa963e4c225b6d5fb3fa087e Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 25 Nov 2025 08:40:33 +0700 Subject: [PATCH 183/184] feat(seeder): add detailed order seeder with customer and meta data Replace generic factory with specific order data including customer information and metadata for testing purposes. The seeder now creates realistic orders with associated customers and their metadata. --- database/seeders/CustomerSeeder.php | 1007 ++++++++++++++++++++++++++- database/seeders/OrderSeeder.php | 197 +++++- 2 files changed, 1196 insertions(+), 8 deletions(-) diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php index 923c88b..17008c4 100644 --- a/database/seeders/CustomerSeeder.php +++ b/database/seeders/CustomerSeeder.php @@ -4,11 +4,1016 @@ use Illuminate\Database\Seeder; use App\Models\Customer; +use App\Models\Order; +use App\Models\Product; class CustomerSeeder extends Seeder { public function run() { - Customer::factory(100)->create(); + $customers = [ + [ + 'name' => 'Nyonya TRI WHYDHARTI', + 'phone' => '082264079363', + 'address' => 'Baciro Sanggrahan Gondokusuman 4/105 Yogyakarta, Rukun Tetangga 042, Rukun Warga 011, Kelurahan Baciro, Kecamatan Gondokusuman, Kota Yogyakarta', + 'created_at' => '2025-11-24T08:04:08.000000Z', + 'updated_at' => '2025-11-24T08:04:08.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA KK PIYUNGAN'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00555', + 'order_date' => '2025-11-24', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '86/2025', + '3' => '2025-11-23T17:00:00.000Z', + '5' => '75000000', + '7' => '2028-11-23T17:00:00.000Z', + '8' => 'HM 12345/Baciro', + '9' => '3404010107890', + '10' => '34.71.100.004.018-0045.0', + '11' => 'Nyonya TRI WHYDHARTI', + '14' => 93750000, + '33' => 'HM 11678/Baciro' + ], + 'created_at' => '2025-11-24T08:30:00.000000Z', + 'updated_at' => '2025-11-24T08:30:00.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya MUJIYEM', + 'phone' => '081804275558', + 'address' => 'Burikan, RT 005, RW 005, Desa Sumberadi, Kecamatan Mlati, Kabupaten Sleman', + 'created_at' => '2025-11-24T07:06:24.000000Z', + 'updated_at' => '2025-11-24T07:06:24.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR BBA'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00554', + 'order_date' => '2025-11-24', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '85', + '3' => '2025-11-23T17:00:00.000Z', + '5' => '50000000', + '9' => '13040605.09816', + '10' => '34.04.060.002.020-0152.0', + '11' => 'Nyonya MUJIYEM', + '14' => 62500000, + '33' => 'HM 10569/SUMBERADI' + ], + 'created_at' => '2025-11-24T07:07:39.000000Z', + 'updated_at' => '2025-11-24T07:07:39.000000Z' + ], + [ + 'no_order' => 'AN00556', + 'order_date' => '2025-11-24', + 'product_id' => 1, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '87', + '3' => '2025-11-23T17:00:00.000Z', + '5' => '30000000', + '7' => '2026-11-23T17:00:00.000Z', + '8' => 'SHM NIB 13.02.000012345.0', + '9' => '13040605.09817', + '10' => '34.04.060.002.020-0153.0', + '11' => 'Nyonya MUJIYEM', + '14' => 37500000, + '33' => 'HM 10570/SUMBERADI' + ], + 'created_at' => '2025-11-24T08:45:00.000000Z', + 'updated_at' => '2025-11-24T08:45:00.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan BUDI WIDODO', + 'phone' => '085868542340', + 'address' => 'Butuh, RT 001, RW 001, Desa Muruh, Kecamatan Gantiwarno, Kabupaten Klaten', + 'created_at' => '2025-11-24T07:02:18.000000Z', + 'updated_at' => '2025-11-24T07:02:18.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR BBA'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00553', + 'order_date' => '2025-11-24', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '84', + '3' => '2025-11-23T17:00:00.000Z', + '5' => '180000000', + '9' => '11.19.02.09.00655', + '10' => '33.10.020.011.007-0066.0', + '11' => 'Tuan BUDI WIDODO', + '14' => 225000000, + '33' => 'HM 01614/MURUH' + ], + 'created_at' => '2025-11-24T07:04:08.000000Z', + 'updated_at' => '2025-11-24T07:04:08.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan ANDI TRISETIAWAN', + 'phone' => '088233435561', + 'address' => 'Bobung, Rukun Tetangga 009, Rukun Warga 002, Desa Putat, Kecamatan Patuk, Kabupaten Gunungkidul', + 'created_at' => '2025-11-21T09:23:54.000000Z', + 'updated_at' => '2025-11-21T09:23:54.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR PALA WNO'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00551', + 'order_date' => '2025-11-21', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '170/2025', + '3' => '2025-11-20T17:00:00.000Z', + '5' => '35000000', + '7' => '2028-11-20T17:00:00.000Z', + '8' => 'SHM NIB 13.02.000009471.0', + '9' => '-', + '10' => '34.03.100.006.008-0323.0', + '11' => 'ANDI TRISETIAWAN', + '12' => '-', + '14' => 50000000, + '55' => '-' + ], + 'created_at' => '2025-11-21T09:26:43.000000Z', + 'updated_at' => '2025-11-21T09:26:43.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan YOYOK SUPRIADI', + 'phone' => '085784857779', + 'address' => 'Jlagran Gedongtengen 2/351, Rukun Tetangga 015, Rukun Warga 003, Kelurahan Pringgokusuman, Kecamatan Gedongtengen, Kota Yogyakarta', + 'created_at' => '2025-11-21T09:22:34.000000Z', + 'updated_at' => '2025-11-21T09:22:34.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'KOPERASI ARTHA KENCANA'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00552', + 'order_date' => '2025-11-21', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '82', + '3' => '2025-11-20T17:00:00.000Z', + '5' => '50000000', + '8' => null, + '9' => '13.05.000003240.0', + '10' => '34.71.120.001.001-0127.0', + '11' => 'YOYOK SUPRIADI', + '14' => 65000000 + ], + 'created_at' => '2025-11-21T09:27:29.000000Z', + 'updated_at' => '2025-11-21T09:27:29.000000Z' + ], + [ + 'no_order' => 'AN00557', + 'order_date' => '2025-11-21', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '88', + '3' => '2025-11-20T17:00:00.000Z', + '5' => '25000000', + '17' => 'BPKB Nomor: D-12345678', + '18' => '45000000', + '19' => 'YOYOK SUPRIADI', + '20' => '45000000', + '21' => '3401234567890123' + ], + 'created_at' => '2025-11-21T10:15:00.000000Z', + 'updated_at' => '2025-11-21T10:15:00.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya MUNAH', + 'phone' => '085790665374', + 'address' => 'Jalan Grinjing Nomor 17 Papringan, Rukun Tetangga 017, Rukun Warga 006, Desa Caturtunggal, Kecamatan Depok, Kabupaten Sleman', + 'created_at' => '2025-11-21T09:16:16.000000Z', + 'updated_at' => '2025-11-21T09:16:16.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00550', + 'order_date' => '2025-11-21', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '83', + '3' => '2025-11-20T17:00:00.000Z', + '5' => '13500000', + '17' => 'BPKB Nomor: R-01906175 I', + '18' => '19500000', + '19' => 'MUNAH', + '20' => '19500000', + '21' => '3308207112940006', + '55' => '835/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-21T09:19:31.000000Z', + 'updated_at' => '2025-11-21T09:19:31.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan SUGIYARTO', + 'phone' => '083173486696', + 'address' => 'Sambirejo, Rukun Tetangga 005, Rukun Warga 004, Desa Semanu, Kecamatan Semanu, Kabupaten Gunungkidul', + 'created_at' => '2025-11-21T09:12:29.000000Z', + 'updated_at' => '2025-11-21T09:12:29.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR ARUM MANDIRI'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00549', + 'order_date' => '2025-11-21', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '167/2025', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '10000000', + '7' => '2027-05-18T17:00:00.000Z', + '8' => '02664/Semanu', + '9' => '1302050502509', + '10' => '34.03.050.005.009-0047.0', + '11' => 'TUKILAH', + '12' => '-', + '13' => '-', + '14' => 87421000, + '55' => '-' + ], + 'created_at' => '2025-11-21T09:18:43.000000Z', + 'updated_at' => '2025-11-21T09:18:43.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan DRS. ISKAK RUSMADI', + 'phone' => '081804329151', + 'address' => 'Sokokerep, Rukun Tetangga 007, Rukun Warga 049, Desa Semanu, Kecamatan Semanu, Kabupaten Gunungkidul', + 'created_at' => '2025-11-21T09:06:12.000000Z', + 'updated_at' => '2025-11-21T09:06:12.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR ARUM MANDIRI'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00548', + 'order_date' => '2025-11-21', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '81', + '3' => '2025-11-20T17:00:00.000Z', + '5' => '5000000', + '17' => 'BPKB O-07842719 I', + '18' => '9800000', + '19' => 'DRS ISKAK RUSMADI', + '20' => '9800000', + '21' => '696120393545', + '55' => '-' + ], + 'created_at' => '2025-11-21T09:09:18.000000Z', + 'updated_at' => '2025-11-21T09:09:18.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan GATOT WUKIR SARTOPO', + 'phone' => '081802735959', + 'address' => 'Pacing Kidul, Rukun Tetangga 005, Rukun Warga 023, Desa Pacarejo, Kecamatan Semanu, Kabupaten Gunungkidul', + 'created_at' => '2025-11-21T09:01:33.000000Z', + 'updated_at' => '2025-11-21T09:01:33.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR ARUM MANDIRI'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00547', + 'order_date' => '2025-11-21', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '74', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '20000000', + '17' => 'BPKB V-06238878', + '18' => '71400000', + '19' => 'ELISA FEBRIANA', + '20' => '71400000', + '21' => '959384611545000', + '55' => '-' + ], + 'created_at' => '2025-11-21T09:03:48.000000Z', + 'updated_at' => '2025-11-21T09:03:48.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya Ir. MARSIYATI', + 'phone' => '081328156455', + 'address' => 'Nitiprayan, RT 002, RW 000, Desa Ngestiharjo, Kecamatan Kasihan, Kabupaten Bantul', + 'created_at' => '2025-11-21T05:40:17.000000Z', + 'updated_at' => '2025-11-21T05:40:17.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR BBA'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00546', + 'order_date' => '2025-11-21', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '80', + '3' => '2025-11-20T17:00:00.000Z', + '5' => '225000000', + '9' => '13010304.25614', + '10' => '34.02.150.001.017-0602.0', + '11' => 'Ir. MARSIYATI', + '14' => 281250000, + '33' => 'HM. 21314/Bangunjiwo' + ], + 'created_at' => '2025-11-21T05:42:00.000000Z', + 'updated_at' => '2025-11-21T05:42:00.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan AFANDI NUGROHO', + 'phone' => '+62 87775757493', + 'address' => 'Kedaton, Rukun Tetangga 001, Rukun Warga 000, Desa Pleret, Kecamatan Pleret, Kabupaten Bantul', + 'created_at' => '2025-11-19T09:27:55.000000Z', + 'updated_at' => '2025-11-19T09:27:55.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR DANAMAS PRIMA'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00545', + 'order_date' => '2025-11-19', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '73', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '20000000', + '17' => 'BPKB Nomor: Q-01258649 I', + '18' => '75000000', + '19' => 'MEILINA DUIKORINA', + '20' => '75000000', + '21' => '-', + '55' => '832/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-19T09:29:35.000000Z', + 'updated_at' => '2025-11-19T09:29:35.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya YUNIARTI', + 'phone' => '081393717662', + 'address' => 'Pajangan, Rukun Tetangga 003, Rukun Warga 010, Desa Sendangtirto, Kecamatan Berbah, Kabupaten Sleman', + 'created_at' => '2025-11-19T09:01:16.000000Z', + 'updated_at' => '2025-11-19T09:01:16.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00544', + 'order_date' => '2025-11-19', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '70', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '45000000', + '17' => 'BPKB Nomor: M-12286246', + '18' => '75000000', + '19' => 'SIGIT', + '20' => '75000000', + '21' => '3471125005690002', + '55' => '830/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-19T09:03:16.000000Z', + 'updated_at' => '2025-11-19T09:03:16.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan TUKIMAN', + 'phone' => '085878069250', + 'address' => 'Temuwuh, RT 003, RW 000, Desa Temuruh, Kecamatan Dlingo, Kabupaten Bantul', + 'created_at' => '2025-11-19T08:26:12.000000Z', + 'updated_at' => '2025-11-19T08:26:12.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR PALA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00543', + 'order_date' => '2025-11-19', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '72', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '260000000', + '8' => 'HM. 00821/Temuwuh', + '9' => '13.01.17.04.00466', + '10' => '34.02.100.004.011-0183.0', + '11' => 'Haris Pujianto Alias Tukiman', + '14' => 50000000 + ], + 'created_at' => '2025-11-19T08:27:55.000000Z', + 'updated_at' => '2025-11-19T08:27:55.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya SUMARNI', + 'phone' => '08', + 'address' => 'Grogol 6, Rukun Tetangga 007, Rukun Warga 006, Desa Bejiharjo, Kecamatan Karangmojo, Kabupaten Gunungkidul', + 'created_at' => '2025-11-19T08:02:17.000000Z', + 'updated_at' => '2025-11-19T08:02:17.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR ARUM MANDIRI'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00542', + 'order_date' => '2025-11-19', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '64', + '3' => '2025-11-17T17:00:00.000Z', + '5' => '9000000', + '17' => 'FC BPKB P-01862335 I', + '18' => '13500000', + '19' => 'SLAMET', + '20' => '13500000', + '21' => '-', + '55' => '-' + ], + 'created_at' => '2025-11-19T08:04:11.000000Z', + 'updated_at' => '2025-11-19T08:04:11.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya NINING PUSPITASARI', + 'phone' => '081328405191', + 'address' => 'Nglebak, Rukun Tetangga 009, Rukun Warga -, Desa Palbapang, Kecamatan Bantul, Kabupaten Bantul', + 'created_at' => '2025-11-19T07:58:08.000000Z', + 'updated_at' => '2025-11-19T07:58:08.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA BANTUL'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00541', + 'order_date' => '2025-11-19', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '71', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '25000000', + '17' => 'BPKB Nomor: O-07875341', + '18' => '115000000', + '19' => 'NINING PUSPITASARI', + '20' => '115000000', + '21' => '3402086909790005', + '55' => '831/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-19T08:02:27.000000Z', + 'updated_at' => '2025-11-19T08:02:27.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan KALIS SULIA ATMOJO', + 'phone' => '085234273005', + 'address' => 'Sumbermulyo, Rukun Tetangga 004, Rukun Warga 003, Desa Kepek, Kecamatan Wonosari, Kabupaten Gunungkidul', + 'created_at' => '2025-11-19T07:56:29.000000Z', + 'updated_at' => '2025-11-19T07:56:29.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR PALA WNO'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00540', + 'order_date' => '2025-11-19', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '166/2025', + '3' => '2025-11-18T17:00:00.000Z', + '5' => '40000000', + '7' => '2028-11-18T17:00:00.000Z', + '8' => '00679/Karangrejek', + '9' => '1302080700701', + '10' => '34.03.080.007.016-0055.0', + '11' => 'SAMIRAN', + '12' => '-', + '13' => 'A0 102431', + '14' => 60000000, + '55' => '-' + ], + 'created_at' => '2025-11-19T07:59:45.000000Z', + 'updated_at' => '2025-11-19T07:59:45.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya HARTINI', + 'phone' => '083854230787', + 'address' => 'Gunting, Rukun Tetangga 0003, Rukun Warga -, Desa Gilangharjo, Kecamatan Pandak, Kabupaten Bantul', + 'created_at' => '2025-11-17T06:11:52.000000Z', + 'updated_at' => '2025-11-17T06:11:52.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA BANTUL'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00538', + 'order_date' => '2025-11-17', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '59', + '3' => '2025-11-16T17:00:00.000Z', + '5' => '12000000', + '17' => 'BPKB Nomor: S-01417439 I', + '18' => '20000000', + '19' => 'HERI KURNIAWAN', + '20' => '20000000', + '21' => '-', + '55' => '824/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-17T06:13:04.000000Z', + 'updated_at' => '2025-11-17T06:13:04.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan SUPRIYADI', + 'phone' => '081252240395', + 'address' => 'Deresan Dukuh Deresan, Rukun Tetangga 002, Rukun Warga -, Desa Ringin Harjo, Kecamatan Bantul, Kabupaten Bantul', + 'created_at' => '2025-11-17T06:08:18.000000Z', + 'updated_at' => '2025-11-17T06:08:18.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA BANTUL'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00537', + 'order_date' => '2025-11-17', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '58', + '3' => '2025-11-16T17:00:00.000Z', + '5' => '35000000', + '17' => 'BPKB Nomor: Q-01227826', + '18' => '100000000', + '19' => 'INTAN PRIDANI PUTRI PRASTIWI', + '20' => '100000000', + '21' => '-', + '55' => '823/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-17T06:09:42.000000Z', + 'updated_at' => '2025-11-17T06:09:42.000000Z' + ] + ] + ], + [ + 'name' => 'MURTONO', + 'phone' => '081328610235', + 'address' => 'Glagah, Rukun Tetangga 006, Rukun Warga 006, Desa Kemiri, Kecamatan Tanjungsari, Kabupaten Gunungkidul', + 'created_at' => '2025-11-15T07:43:09.000000Z', + 'updated_at' => '2025-11-15T07:43:09.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR PALA WNO'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00536', + 'order_date' => '2025-11-14', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '5' => '100000000', + '10' => '34.03.070.001.001-0017.0', + '11' => 'MURTONO', + '13' => 'A8643216', + '14' => 60000000, + '33' => 'HM NIB 13.02.000030081.0', + '55' => '-' + ], + 'created_at' => '2025-11-15T07:50:13.000000Z', + 'updated_at' => '2025-11-15T07:51:49.000000Z' + ], + [ + 'no_order' => 'AN00535', + 'order_date' => '2025-11-15', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '5' => '100000000', + '9' => '-', + '10' => '34.03.070.001.004-0004.0', + '11' => 'HARTO WIYONO', + '12' => '-', + '13' => 'AF 485263', + '14' => 90000000, + '33' => '00467/Bendungan', + '55' => '-' + ], + 'created_at' => '2025-11-15T07:46:39.000000Z', + 'updated_at' => '2025-11-15T07:46:39.000000Z' + ], + [ + 'no_order' => 'AN00558', + 'order_date' => '2025-11-15', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '168/2025', + '3' => '2025-11-14T17:00:00.000Z', + '5' => '150000000', + '7' => '2029-11-14T17:00:00.000Z', + '8' => 'HM 00900/Kemiri', + '9' => '13.05.17.06.00789', + '10' => '34.03.070.001.005-0012.0', + '11' => 'MURTONO', + '14' => 187500000, + '33' => 'HM 00901/Kemiri' + ], + 'created_at' => '2025-11-15T08:30:00.000000Z', + 'updated_at' => '2025-11-15T08:30:00.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya MIPAH YULIANTI', + 'phone' => '081329805861', + 'address' => 'Soboman, RT 005, RW 000, Desa Ngestiharjo, Kecamatan Kasihan, Kabupaten Bantul', + 'created_at' => '2025-11-14T08:43:43.000000Z', + 'updated_at' => '2025-11-14T08:43:43.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA KK KADIPIRO'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00534', + 'order_date' => '2025-11-14', + 'product_id' => 26, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'Kesepakatan Jual Beli, Surat Kuasa Menjual', + '2' => '52 ; 53', + '3' => '2025-11-13T17:00:00.000Z', + '5' => '350000000', + '19' => 'Nyonya MIPAH YULIANTI', + '20' => '525000000', + '30' => '2025-11-13T17:00:00.000Z', + '33' => 'HM 09346/Ngestiharjo', + '55' => '821/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-14T08:48:25.000000Z', + 'updated_at' => '2025-11-14T08:48:25.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan FATAJI SUSIADI', + 'phone' => '089674435783', + 'address' => 'Jl. Maundri No. 6A, Rejokusuman, Sokowaten, RT 004, RW 000, Desa Tamanan, Kecamatan Banguntapan, Kabupaten Bantul', + 'created_at' => '2025-11-14T08:39:51.000000Z', + 'updated_at' => '2025-11-14T08:39:51.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00533', + 'order_date' => '2025-11-13', + 'product_id' => 26, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'Perjanjian Kredit ; Surat Kuasa Membebankan Hak Tanggungan', + '2' => '42 ; 43', + '3' => '2025-11-12T17:00:00.000Z', + '5' => '450000000', + '19' => 'FATAJI SUSIADI', + '20' => '675000000', + '30' => '2025-11-12T17:00:00.000Z', + '33' => 'HM 06396/Tamanan', + '55' => '815/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-14T08:42:46.000000Z', + 'updated_at' => '2025-11-14T08:42:46.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan EKO SUHARTONO, Bachelor of Science', + 'phone' => '082220003546', + 'address' => 'Jomblangan, Rukun Tetangga 004, Rukun Warga -, Desa Banguntapan, Kecamatan Banguntapan, Kabupaten Bantul', + 'created_at' => '2025-11-14T08:38:43.000000Z', + 'updated_at' => '2025-11-14T08:38:43.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00532', + 'order_date' => '2025-11-14', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '51', + '3' => '2025-11-13T17:00:00.000Z', + '5' => '15000000', + '17' => 'BPKB Nomor: S-01341505', + '18' => '110000000', + '19' => 'LUCIA ETTY KRISTIANI', + '20' => '110000000', + '21' => '-', + '55' => '820/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-14T08:40:32.000000Z', + 'updated_at' => '2025-11-14T08:40:32.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan ANDI PASKAH KURNIAWAN', + 'phone' => '08994565689', + 'address' => 'Kitren Kotagede 2/664, Rukun Tetangga 036, Rukun Warga 008, Kelurahan Prenggan, Kecamatan Kotagede, Kota Yogyakarta', + 'created_at' => '2025-11-14T08:35:51.000000Z', + 'updated_at' => '2025-11-14T08:35:51.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00531', + 'order_date' => '2025-11-14', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '50', + '3' => '2025-11-13T17:00:00.000Z', + '5' => '22000000', + '17' => '1. BPKB Nomor: R-01828236 I, 2. BPKB Nomor: N-10675133 I', + '18' => '38000000', + '19' => '1. WINARTI, S.Pd., 2. ANDREAS WIRATSONGKO', + '20' => '38000000', + '21' => '-', + '55' => '819/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-14T08:37:45.000000Z', + 'updated_at' => '2025-11-14T08:37:45.000000Z' + ] + ] + ], + [ + 'name' => 'Nyonya VERONIKA ELYSA KURNIADEWI', + 'phone' => '08158791209', + 'address' => 'Perumahan Sendok Indah Kotagede II/373, Rukun Tetangga 020, Rukun Warga 004, Kelurahan Prenggan, Kecamatan Kotagede, Kota Yogyakarta', + 'created_at' => '2025-11-14T08:26:09.000000Z', + 'updated_at' => '2025-11-14T08:26:09.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA PUSAT'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00530', + 'order_date' => '2025-11-14', + 'product_id' => 25, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'Perjanjian Pengikatan Jaminan Fidusia & Perjanjian Kredit Notariil', + '2' => '55', + '3' => '2025-11-13T17:00:00.000Z', + '5' => '85000000', + '17' => 'BPKB Nomor: P-02805918 I', + '18' => '220000000', + '19' => 'VERONIKA ELYSA KURNIADEWI', + '20' => '220000000', + '21' => '-', + '33' => 'BPKB Nomor: P-02805918 I', + '55' => '-' + ], + 'created_at' => '2025-11-14T08:28:41.000000Z', + 'updated_at' => '2025-11-14T08:28:41.000000Z' + ] + ] + ], + [ + 'name' => 'Tuan NGADIMIN', + 'phone' => '0819 1462 7639', + 'address' => 'Warak Kidul, Rukun Tetangga 003, Rukun Warga 009, Desa Sumberadi, Kecamatan Mlati, Kabupaten Sleman.', + 'created_at' => '2025-11-14T04:14:51.000000Z', + 'updated_at' => '2025-11-14T04:14:51.000000Z', + 'meta' => [ + ['meta_key' => 'bank', 'meta_value' => 'BPR NUSAMBA KK PIYUNGAN'] + ], + 'orders' => [ + [ + 'no_order' => 'AN00529', + 'order_date' => '2025-11-14', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '49', + '3' => '2025-11-13T17:00:00.000Z', + '5' => '30000000', + '17' => 'BPKB Nomor: K-03108372 I', + '18' => '100000000', + '19' => 'UTI HARTATI', + '20' => '100000000', + '21' => '-', + '55' => '818/ZPW/LEG/XI/2025' + ], + 'created_at' => '2025-11-14T04:16:19.000000Z', + 'updated_at' => '2025-11-14T04:16:19.000000Z' + ], + [ + 'no_order' => 'AN00559', + 'order_date' => '2025-11-14', + 'product_id' => 1, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '2' => '56', + '3' => '2025-11-13T17:00:00.000Z', + '5' => '120000000', + '7' => '2027-11-13T17:00:00.000Z', + '8' => 'SHM NIB 13.02.000045678.0', + '9' => '1302080601234', + '10' => '34.03.080.007.017-0056.0', + '11' => 'NGADIMIN', + '14' => 150000000, + '33' => 'HM 01234/Sumberadi' + ], + 'created_at' => '2025-11-14T09:30:00.000000Z', + 'updated_at' => '2025-11-14T09:30:00.000000Z' + ], + [ + 'no_order' => 'AN00560', + 'order_date' => '2025-11-14', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'meta' => [ + '5' => '80000000', + '9' => '1302080601235', + '10' => '34.03.080.007.018-0057.0', + '11' => 'NGADIMIN', + '13' => 'A7654321', + '14' => 100000000, + '33' => 'HM 01235/Sumberadi' + ], + 'created_at' => '2025-11-14T10:45:00.000000Z', + 'updated_at' => '2025-11-14T10:45:00.000000Z' + ] + ] + ], + ]; + + // Insert specific customers with their meta and order data + foreach ($customers as $customerData) { + $meta = $customerData['meta'] ?? []; + $orders = $customerData['orders'] ?? []; + unset($customerData['meta']); + unset($customerData['orders']); + + $customer = Customer::create($customerData); + + // Insert meta data for the customer + foreach ($meta as $metaData) { + $customer->meta()->create($metaData); + } + + // Insert orders for the customer + foreach ($orders as $orderData) { + $orderMeta = $orderData['meta'] ?? []; + unset($orderData['meta']); + + $order = $customer->orders()->create($orderData); + + // Insert meta data for the order + foreach ($orderMeta as $key => $value) { + $order->meta()->create([ + 'meta_key' => $key, + 'meta_value' => $value + ]); + } + } + } + + // Create additional random customers if needed + Customer::factory(50)->create(); } } diff --git a/database/seeders/OrderSeeder.php b/database/seeders/OrderSeeder.php index eeeb352..86c2516 100644 --- a/database/seeders/OrderSeeder.php +++ b/database/seeders/OrderSeeder.php @@ -2,17 +2,200 @@ namespace Database\Seeders; -use App\Models\Order; use Illuminate\Database\Seeder; +use App\Models\Order; +use App\Models\Customer; +use App\Models\Product; class OrderSeeder extends Seeder { - /** - * Run the database seeds. - */ - public function run(): void + public function run() { - // Create 10 random orders - Order::factory(20)->create(); + $peroranganOrders = [ + [ + 'no_order' => 'AN00561', + 'order_date' => '2025-11-25', + 'product_id' => 1, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'customer' => [ + 'name' => 'Tuan AHMAD RIZKI', + 'phone' => '081223345678', + 'address' => 'Jl. Malioboro No. 45, Gedongtengen, Kecamatan Gondokusuman, Kota Yogyakarta' + ], + 'meta' => [ + '1' => 'Akta Jual Beli', + '2' => '89/2025', + '3' => '2025-11-24T17:00:00.000Z', + '5' => '250000000', + '7' => '2026-11-24T17:00:00.000Z', + '8' => 'SHM NIB 13.02.000056789.0', + '9' => '3404010123456', + '10' => '34.71.100.004.019-0056.0', + '11' => 'AHMAD RIZKI', + '12' => '-', + '14' => 312500000, + '33' => 'HM 23456/Gedongtengen' + ] + ], + [ + 'no_order' => 'AN00562', + 'order_date' => '2025-11-25', + 'product_id' => 2, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'customer' => [ + 'name' => 'Nyonya SITI NURHALIZAH', + 'phone' => '087654321098', + 'address' => 'Perumahan Griya Citra Asri Blok A No. 12, Condongcatur, Kecamatan Depok, Kabupaten Sleman' + ], + 'meta' => [ + '2' => '90/2025', + '3' => '2025-11-24T17:00:00.000Z', + '5' => '150000000', + '7' => '2027-11-24T17:00:00.000Z', + '8' => 'HM 34567/Condongcatur', + '9' => '1302050701234', + '10' => '34.03.080.007.019-0067.0', + '11' => 'SITI NURHALIZAH', + '14' => 187500000, + '33' => 'HM 34568/Condongcatur' + ] + ], + [ + 'no_order' => 'AN00563', + 'order_date' => '2025-11-25', + 'product_id' => 3, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'customer' => [ + 'name' => 'Tuan BAMBANG SUGIANTO', + 'phone' => '082345678901', + 'address' => 'Jl. Parangtritis Km 8, Sewon, Bantul, DIY' + ], + 'meta' => [ + '5' => '300000000', + '9' => '1301030456789', + '10' => '34.02.150.001.018-0089.0', + '11' => 'BAMBANG SUGIANTO', + '13' => 'A1234567', + '14' => 375000000, + '33' => 'HM 456789/Sewon' + ] + ], + [ + 'no_order' => 'AN00564', + 'order_date' => '2025-11-25', + 'product_id' => 4, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'customer' => [ + 'name' => 'Nyonya DEWI LESTARI', + 'phone' => '089876543210', + 'address' => 'Jl. Kaliurang Km 10, Ngaglik, Sleman, DIY' + ], + 'meta' => [ + '1' => 'PERJANJIAN PENGIKATAN JAMINAN FIDUSIA', + '2' => '91', + '3' => '2025-11-24T17:00:00.000Z', + '5' => '50000000', + '17' => 'BPKB Nomor: AB-12345678', + '18' => '85000000', + '19' => 'DEWI LESTARI', + '20' => '85000000', + '21' => '3401023456789012' + ] + ], + [ + 'no_order' => 'AN00565', + 'order_date' => '2025-11-25', + 'product_id' => 1, + 'price' => 0, + 'payment_method' => 'Transfer', + 'paid' => 0, + 'customer' => [ + 'name' => 'Tuan SLAMET RAHARJO', + 'phone' => '081234567890', + 'address' => 'Jl. Wates Km 12, Pengasih, Kulon Progo, DIY' + ], + 'meta' => [ + '2' => '92/2025', + '3' => '2025-11-24T17:00:00.000Z', + '5' => '175000000', + '7' => '2028-11-24T17:00:00.000Z', + '8' => 'SHM NIB 13.02.000067890.0', + '9' => '3403010234567', + '10' => '34.01.020.003.012-0098.0', + '11' => 'SLAMET RAHARJO', + '14' => 218750000, + '33' => 'HM 567890/Pengasih' + ] + ] + ]; + + // Insert perorangan orders with customer and meta data + foreach ($peroranganOrders as $orderData) { + $customerData = $orderData['customer']; + $orderMeta = $orderData['meta'] ?? []; + + // Extract order data (remove customer and meta) + $orderInfo = [ + 'no_order' => $orderData['no_order'], + 'order_date' => $orderData['order_date'], + 'product_id' => $orderData['product_id'], + 'price' => $orderData['price'], + 'payment_method' => $orderData['payment_method'], + 'paid' => $orderData['paid'], + 'created_at' => '2025-11-25T10:00:00.000000Z', + 'updated_at' => '2025-11-25T10:00:00.000000Z' + ]; + + unset($orderData['customer']); + unset($orderData['meta']); + + // Create or find customer + $customer = Customer::firstOrCreate( + ['phone' => $customerData['phone']], + [ + 'name' => $customerData['name'], + 'address' => $customerData['address'], + 'created_at' => '2025-11-25T09:00:00.000000Z', + 'updated_at' => '2025-11-25T09:00:00.000000Z' + ] + ); + + // Create order + $order = $customer->orders()->create($orderInfo); + + // Create order meta data + foreach ($orderMeta as $key => $value) { + $order->meta()->create([ + 'meta_key' => $key, + 'meta_value' => $value + ]); + } + + // Add bank meta to customer (random banks with full names) + $banks = [ + 'BPR NUSAMBA PUSAT', + 'BPR BBA', + 'BPR PALA WNO', + 'BPR ARUM MANDIRI', + 'BPR NUSAMBA BANTUL', + 'BPR DANAMAS PRIMA', + 'KOPERASI ARTHA KENCANA', + 'BPR NUSAMBA KK PIYUNGAN', + 'BPR NUSAMBA KK KADIPIRO' + ]; + + $customer->meta()->create([ + 'meta_key' => 'bank', + 'meta_value' => $banks[array_rand($banks)] + ]); + } } } From 783bdbb9a1067ef77a94184042e41d71701b3d86 Mon Sep 17 00:00:00 2001 From: aadiityaak Date: Tue, 25 Nov 2025 12:16:09 +0700 Subject: [PATCH 184/184] refactor(seeders): optimize order and customer seeding logic - Replace loop-based meta creation with direct assignment in CustomerSeeder - Move customer and order seeding to dedicated seeders in DatabaseSeeder - Restructure OrderSeeder with separate perorangan and bank order sections - Add detailed bank order examples with proper metadata --- database/seeders/CustomerSeeder.php | 8 +-- database/seeders/DatabaseSeeder.php | 21 +----- database/seeders/OrderSeeder.php | 99 +++++++++++++++++++++++------ 3 files changed, 84 insertions(+), 44 deletions(-) diff --git a/database/seeders/CustomerSeeder.php b/database/seeders/CustomerSeeder.php index 17008c4..41591d0 100644 --- a/database/seeders/CustomerSeeder.php +++ b/database/seeders/CustomerSeeder.php @@ -1004,11 +1004,9 @@ public function run() $order = $customer->orders()->create($orderData); // Insert meta data for the order - foreach ($orderMeta as $key => $value) { - $order->meta()->create([ - 'meta_key' => $key, - 'meta_value' => $value - ]); + if (!empty($orderMeta)) { + $order->meta = $orderMeta; + $order->save(); } } } diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 328c187..33a78ca 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -24,26 +24,9 @@ public function run(): void UserSeeder::class, ProductSeeder::class, CategorySeeder::class, + CustomerSeeder::class, + OrderSeeder::class, PostSeeder::class, - ]); - - // Seed customers and orders - $customers = Customer::factory(28)->create(); - - foreach ($customers as $customer) { - $ordersCount = rand(2, 4); - $orders = Order::factory($ordersCount)->create(['customer_id' => $customer->id]); - - foreach ($orders as $order) { - $jobdesksCount = rand(2, 5); - Jobdesk::factory($jobdesksCount)->create([ - 'order_id' => $order->id, - ]); - } - } - - // Seed notifications (after users, customers, and orders are created) - $this->call([ NotificationSeeder::class, ]); } diff --git a/database/seeders/OrderSeeder.php b/database/seeders/OrderSeeder.php index 86c2516..8863b9b 100644 --- a/database/seeders/OrderSeeder.php +++ b/database/seeders/OrderSeeder.php @@ -137,7 +137,7 @@ public function run() ] ]; - // Insert perorangan orders with customer and meta data + // Insert 5 perorangan orders (individual customers) foreach ($peroranganOrders as $orderData) { $customerData = $orderData['customer']; $orderMeta = $orderData['meta'] ?? []; @@ -172,29 +172,88 @@ public function run() $order = $customer->orders()->create($orderInfo); // Create order meta data - foreach ($orderMeta as $key => $value) { - $order->meta()->create([ - 'meta_key' => $key, - 'meta_value' => $value - ]); - } - - // Add bank meta to customer (random banks with full names) - $banks = [ - 'BPR NUSAMBA PUSAT', - 'BPR BBA', - 'BPR PALA WNO', - 'BPR ARUM MANDIRI', - 'BPR NUSAMBA BANTUL', - 'BPR DANAMAS PRIMA', - 'KOPERASI ARTHA KENCANA', - 'BPR NUSAMBA KK PIYUNGAN', - 'BPR NUSAMBA KK KADIPIRO' + $order->meta = $orderMeta; + $order->save(); + + // Add Perorangan meta for these individual customers + $customer->meta()->create([ + 'meta_key' => 'bank', + 'meta_value' => 'Perorangan' + ]); + } + + // Insert bank orders (15 orders with bank customers) + $bankOrders = [ + // BPR NUSAMBA PUSAT orders + ['no_order' => 'BP001', 'product_id' => 2, 'bank' => 'BPR NUSAMBA PUSAT', 'customer_name' => 'PT. MITRA SEJAHTERA', 'customer_phone' => '02745551234', 'customer_address' => 'Jl. Sudirman No. 123, Yogyakarta'], + ['no_order' => 'BP002', 'product_id' => 1, 'bank' => 'BPR NUSAMBA PUSAT', 'customer_name' => 'CV. JAYA ABADI', 'customer_phone' => '02745551123', 'customer_address' => 'Jl. Malioboro No. 56, Yogyakarta'], + ['no_order' => 'BP003', 'product_id' => 3, 'bank' => 'BPR NUSAMBA PUSAT', 'customer_name' => 'PT. BERKAH MULYA', 'customer_phone' => '02745551345', 'customer_address' => 'Jl. Solo Km 12, Yogyakarta'], + + // BPR BBA orders + ['no_order' => 'BB001', 'product_id' => 2, 'bank' => 'BPR BBA', 'customer_name' => 'PT. MAJU JAYA', 'customer_phone' => '027433344567', 'customer_address' => 'Jl. Kaliurang Km 5, Sleman'], + ['no_order' => 'BB002', 'product_id' => 1, 'bank' => 'BPR BBA', 'customer_name' => 'CV. KARYA MANDIRI', 'customer_phone' => '027433344578', 'customer_address' => 'Jl. Gejayan No. 88, Yogyakarta'], + + // BPR PALA WNO orders + ['no_order' => 'PW001', 'product_id' => 3, 'bank' => 'BPR PALA WNO', 'customer_name' => 'PT. INDO TEKNIK', 'customer_phone' => '027422233890', 'customer_address' => 'Jl. Ring Road Utara, Sleman'], + ['no_order' => 'PW002', 'product_id' => 4, 'bank' => 'BPR PALA WNO', 'customer_name' => 'CV. SENTOSA ABADI', 'customer_phone' => '027422233901', 'customer_address' => 'Jl. Magelang Km 10, Yogyakarta'], + + // BPR ARUM MANDIRI orders + ['no_order' => 'AM001', 'product_id' => 2, 'bank' => 'BPR ARUM MANDIRI', 'customer_name' => 'PT. MAHKOTA INDAH', 'customer_phone' => '027411122345', 'customer_address' => 'Jl. Wates Km 8, Bantul'], + ['no_order' => 'AM002', 'product_id' => 1, 'bank' => 'BPR ARUM MANDIRI', 'customer_name' => 'CV. CAHAYA MULIA', 'customer_phone' => '027411122456', 'customer_address' => 'Jl. Parangtritis Km 5, Bantul'], + + // BPR NUSAMBA BANTUL orders + ['no_order' => 'NB001', 'product_id' => 4, 'bank' => 'BPR NUSAMBA BANTUL', 'customer_name' => 'PT. BANTUL SEJAHTERA', 'customer_phone' => '027500998765', 'customer_address' => 'Jl. Bantul Km 3, Bantul'], + ['no_order' => 'NB002', 'product_id' => 3, 'bank' => 'BPR NUSAMBA BANTUL', 'customer_name' => 'CV. NUSANTARA JAYA', 'customer_phone' => '027500998876', 'customer_address' => 'Jl. Imogiri Timur Km 10, Bantul'], + + // BPR DANAMAS PRIMA orders + ['no_order' => 'DP001', 'product_id' => 2, 'bank' => 'BPR DANAMAS PRIMA', 'customer_name' => 'PT. DANAMAS INVESTAMA', 'customer_phone' => '027466677890', 'customer_address' => 'Jl. Godean Km 9, Sleman'], + ['no_order' => 'DP002', 'product_id' => 1, 'bank' => 'BPR DANAMAS PRIMA', 'customer_name' => 'CV. PRIMA KARYA', 'customer_phone' => '027466677901', 'customer_address' => 'Jl. Palagan Km 7, Yogyakarta'], + + // KOPERASI ARTHA KENCANA orders + ['no_order' => 'AK001', 'product_id' => 3, 'bank' => 'KOPERASI ARTHA KENCANA', 'customer_name' => 'KOPERASI KARYA TANI', 'customer_phone' => '027477788012', 'customer_address' => 'Jl. Kaliurang Km 15, Sleman'], + ['no_order' => 'AK002', 'product_id' => 4, 'bank' => 'KOPERASI ARTHA KENCANA', 'customer_name' => 'KOPKAR BERSATU', 'customer_phone' => '027477788123', 'customer_address' => 'Jl. Seturan Raya, Sleman'], + ]; + + // Insert bank orders with bank customers + foreach ($bankOrders as $orderData) { + // Extract order data + $orderInfo = [ + 'no_order' => $orderData['no_order'], + 'order_date' => '2025-11-25', + 'product_id' => $orderData['product_id'], + 'price' => rand(50000000, 500000000), + 'payment_method' => 'Transfer', + 'paid' => 0, + 'created_at' => '2025-11-25T11:00:00.000000Z', + 'updated_at' => '2025-11-25T11:00:00.000000Z' + ]; + + // Create or find bank customer + $customer = Customer::firstOrCreate( + ['phone' => $orderData['customer_phone']], + [ + 'name' => $orderData['customer_name'], + 'address' => $orderData['customer_address'], + 'created_at' => '2025-11-25T10:30:00.000000Z', + 'updated_at' => '2025-11-25T10:30:00.000000Z' + ] + ); + + // Create order + $order = $customer->orders()->create($orderInfo); + + // Create basic order meta data for bank orders + $order->meta = [ + '2' => rand(100, 999) . '/2025', + '3' => '2025-11-24T17:00:00.000Z', + '5' => rand(100000000, 400000000) ]; + $order->save(); + // Add bank meta to customer $customer->meta()->create([ 'meta_key' => 'bank', - 'meta_value' => $banks[array_rand($banks)] + 'meta_value' => $orderData['bank'] ]); } }