From aa233eb793aa8aa50fe1d063b31f0f036f66fcf9 Mon Sep 17 00:00:00 2001 From: arifal Date: Mon, 16 Jun 2025 17:27:59 +0700 Subject: [PATCH] create new menu histori stock audit --- app/Console/Commands/SetupStockAuditMenu.php | 83 ++++ .../StockAuditController.php | 227 ++++++++++ database/seeders/MenuSeeder.php | 4 + docs/STOCK_AUDIT.md | 257 +++++++++++ .../mutations/index.js.map | 2 +- .../warehouse_management/stock_audit/index.js | 32 ++ .../stock_audit/index.js.map | 1 + public/mix-manifest.json | 1 + .../warehouse_management/stock_audit/index.js | 419 ++++++++++++++++++ .../layouts/partials/sidebarMenu.blade.php | 9 + .../stock_audit/index.blade.php | 220 +++++++++ routes/web.php | 6 + webpack.mix.js | 4 + 13 files changed, 1264 insertions(+), 1 deletion(-) create mode 100644 app/Console/Commands/SetupStockAuditMenu.php create mode 100644 app/Http/Controllers/WarehouseManagement/StockAuditController.php create mode 100644 docs/STOCK_AUDIT.md create mode 100644 public/js/warehouse_management/stock_audit/index.js create mode 100644 public/js/warehouse_management/stock_audit/index.js.map create mode 100644 resources/js/warehouse_management/stock_audit/index.js create mode 100644 resources/views/warehouse_management/stock_audit/index.blade.php diff --git a/app/Console/Commands/SetupStockAuditMenu.php b/app/Console/Commands/SetupStockAuditMenu.php new file mode 100644 index 0000000..a6c0e47 --- /dev/null +++ b/app/Console/Commands/SetupStockAuditMenu.php @@ -0,0 +1,83 @@ +info('Setting up Stock Audit menu...'); + + // Check if menu already exists + $existingMenu = Menu::where('link', 'stock-audit.index')->first(); + + if ($existingMenu) { + $this->warn('Stock Audit menu already exists!'); + return 0; + } + + // Create Stock Audit menu + $menu = Menu::create([ + 'name' => 'Audit Histori Stock', + 'link' => 'stock-audit.index', + 'created_at' => now(), + 'updated_at' => now() + ]); + + $this->info('Stock Audit menu created with ID: ' . $menu->id); + + // Give all roles access to this menu + $roles = Role::all(); + $privilegeCount = 0; + + foreach($roles as $role) { + // Check if privilege already exists + $existingPrivilege = Privilege::where('role_id', $role->id) + ->where('menu_id', $menu->id) + ->first(); + + if (!$existingPrivilege) { + Privilege::create([ + 'role_id' => $role->id, + 'menu_id' => $menu->id, + 'create' => 0, // Stock audit is view-only + 'update' => 0, // Stock audit is view-only + 'delete' => 0, // Stock audit is view-only + 'view' => 1, // Allow viewing + 'created_at' => now(), + 'updated_at' => now() + ]); + $privilegeCount++; + } + } + + $this->info("Created {$privilegeCount} privileges for Stock Audit menu."); + $this->info('Stock Audit menu setup completed successfully!'); + + return 0; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/WarehouseManagement/StockAuditController.php b/app/Http/Controllers/WarehouseManagement/StockAuditController.php new file mode 100644 index 0000000..6b055c7 --- /dev/null +++ b/app/Http/Controllers/WarehouseManagement/StockAuditController.php @@ -0,0 +1,227 @@ +first(); + $dealers = Dealer::all(); + $products = Product::all(); + + if ($request->ajax()) { + Log::info('Stock audit ajax request received', [ + 'filters' => $request->only(['dealer', 'product', 'change_type', 'date']), + 'user_id' => auth()->id(), + 'user_dealer_id' => auth()->user()->dealer_id + ]); + $data = StockLog::query() + ->with([ + 'stock.product', + 'stock.dealer', + 'user.role', + 'source' + ]) + ->leftJoin('stocks', 'stock_logs.stock_id', '=', 'stocks.id') + ->leftJoin('products', 'stocks.product_id', '=', 'products.id') + ->leftJoin('dealers', 'stocks.dealer_id', '=', 'dealers.id') + ->leftJoin('users', 'stock_logs.user_id', '=', 'users.id') + ->select('stock_logs.*'); + + // Filter berdasarkan dealer jika user bukan admin + if (auth()->user()->dealer_id) { + $data->whereHas('stock', function($query) { + $query->where('dealer_id', auth()->user()->dealer_id); + }); + } + + // Apply filters from request + if ($request->filled('dealer')) { + $data->where('dealers.name', 'like', '%' . $request->dealer . '%'); + } + + if ($request->filled('product')) { + $data->where('products.name', 'like', '%' . $request->product . '%'); + } + + if ($request->filled('change_type')) { + $data->where('stock_logs.change_type', $request->change_type); + } + + if ($request->filled('date')) { + $data->whereDate('stock_logs.created_at', $request->date); + } + + return DataTables::of($data) + ->addIndexColumn() + ->addColumn('product_name', function($row) { + return $row->stock->product->name ?? '-'; + }) + ->addColumn('dealer_name', function($row) { + return $row->stock->dealer->name ?? '-'; + }) + ->addColumn('change_type', function($row) { + $changeType = $row->change_type; + $class = match($changeType->value) { + 'increase' => 'text-success', + 'decrease' => 'text-danger', + 'adjustment' => 'text-warning', + 'no_change' => 'text-muted', + default => 'text-dark' + }; + + return "{$changeType->label()}"; + }) + ->addColumn('quantity_change', function($row) { + $change = $row->quantity_change; + if ($change > 0) { + return "+{$change}"; + } elseif ($change < 0) { + return "{$change}"; + } else { + return "0"; + } + }) + ->addColumn('stock_before_after', function($row) { + return "{$row->previous_quantity} → {$row->new_quantity}"; + }) + ->addColumn('source_info', function($row) { + if ($row->source_type === 'App\\Models\\Mutation') { + $mutationNumber = $row->source ? $row->source->mutation_number : '-'; + return "Mutasi: {$mutationNumber}"; + } elseif ($row->source_type === 'App\\Models\\Opname') { + return "Opname"; + } else { + return $row->source_type ?? '-'; + } + }) + ->addColumn('user_name', function($row) { + return $row->user->name ?? '-'; + }) + ->addColumn('created_at', function($row) { + return $row->created_at->format('d M Y, H:i'); + }) + ->addColumn('action', function($row) { + $buttons = ''; + return $buttons; + }) + // Filtering + ->filterColumn('product_name', function($query, $keyword) { + $query->where('products.name', 'like', "%{$keyword}%"); + }) + ->filterColumn('dealer_name', function($query, $keyword) { + $query->where('dealers.name', 'like', "%{$keyword}%"); + }) + ->filterColumn('change_type', function($query, $keyword) { + $query->where('stock_logs.change_type', 'like', "%{$keyword}%"); + }) + ->filterColumn('source_info', function($query, $keyword) { + $query->where(function($q) use ($keyword) { + $q->where('stock_logs.source_type', 'like', "%{$keyword}%") + ->orWhere('stock_logs.description', 'like', "%{$keyword}%"); + }); + }) + ->filterColumn('user_name', function($query, $keyword) { + $query->where('users.name', 'like', "%{$keyword}%"); + }) + ->filterColumn('created_at', function($query, $keyword) { + $query->whereDate('stock_logs.created_at', 'like', "%{$keyword}%"); + }) + // Order column mapping + ->orderColumn('product_name', function($query, $order) { + return $query->orderBy('products.name', $order); + }) + ->orderColumn('dealer_name', function($query, $order) { + return $query->orderBy('dealers.name', $order); + }) + ->orderColumn('user_name', function($query, $order) { + return $query->orderBy('users.name', $order); + }) + ->orderColumn('created_at', function($query, $order) { + return $query->orderBy('stock_logs.created_at', $order); + }) + ->orderColumn('quantity_change', function($query, $order) { + return $query->orderBy('stock_logs.quantity_change', $order); + }) + ->orderColumn('stock_before_after', function($query, $order) { + return $query->orderBy('stock_logs.previous_quantity', $order); + }) + ->orderColumn('change_type', function($query, $order) { + return $query->orderBy('stock_logs.change_type', $order); + }) + ->orderColumn('source_info', function($query, $order) { + return $query->orderBy('stock_logs.source_type', $order); + }) + ->rawColumns(['change_type', 'quantity_change', 'action']) + ->make(true); + } + + return view('warehouse_management.stock_audit.index', compact('menu', 'dealers', 'products')); + } + + public function getDetail(StockLog $stockLog) + { + try { + $stockLog->load([ + 'stock.product', + 'stock.dealer', + 'user.role', + 'source' + ]); + + // Format data untuk response + $stockLog->created_at_formatted = $stockLog->created_at->format('d M Y, H:i'); + $stockLog->change_type_label = $stockLog->change_type->label(); + + // Detail source berdasarkan tipe + $sourceDetail = null; + if ($stockLog->source) { + if ($stockLog->source_type === 'App\\Models\\Mutation') { + $mutation = $stockLog->source; + $mutation->load(['fromDealer', 'toDealer', 'requestedBy', 'approvedBy']); + + // Format approved_at date if exists + if ($mutation->approved_at) { + $mutation->approved_at_formatted = $mutation->approved_at->format('d M Y, H:i'); + } + + $sourceDetail = [ + 'type' => 'mutation', + 'data' => $mutation + ]; + } elseif ($stockLog->source_type === 'App\\Models\\StockOpname') { + $opname = $stockLog->source; + $opname->load(['dealer', 'user']); + $sourceDetail = [ + 'type' => 'opname', + 'data' => $opname + ]; + } + } + + return response()->json([ + 'success' => true, + 'data' => $stockLog, + 'source_detail' => $sourceDetail + ]); + + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => 'Gagal memuat detail audit: ' . $e->getMessage() + ], 500); + } + } +} \ No newline at end of file diff --git a/database/seeders/MenuSeeder.php b/database/seeders/MenuSeeder.php index b6c8778..0f524b4 100755 --- a/database/seeders/MenuSeeder.php +++ b/database/seeders/MenuSeeder.php @@ -30,6 +30,10 @@ class MenuSeeder extends Seeder [ 'name' => 'Stock Opname', 'link' => 'opnames.index' + ], + [ + 'name' => 'Histori Stock', + 'link' => 'stock-audit.index' ] ]; diff --git a/docs/STOCK_AUDIT.md b/docs/STOCK_AUDIT.md new file mode 100644 index 0000000..8c890b6 --- /dev/null +++ b/docs/STOCK_AUDIT.md @@ -0,0 +1,257 @@ +# Audit Histori Stock + +## Deskripsi + +Fitur Audit Histori Stock memungkinkan untuk melacak semua perubahan stock yang terjadi di sistem. Setiap kali ada perubahan stock (penambahan, pengurangan, penyesuaian), sistem akan mencatat detail perubahan tersebut untuk keperluan audit. + +## Fitur Utama + +### 1. Tracking Otomatis + +- Sistem otomatis mencatat setiap perubahan stock +- Mencatat stock sebelum dan sesudah perubahan +- Mencatat sumber perubahan (mutasi, opname, dll) +- Mencatat user yang melakukan perubahan +- Mencatat timestamp perubahan + +### 2. Filter dan Pencarian + +- Filter berdasarkan dealer +- Filter berdasarkan produk +- Filter berdasarkan jenis perubahan +- Filter berdasarkan tanggal +- Pencarian realtime pada semua kolom + +### 3. Detail Audit + +- Informasi lengkap perubahan stock +- Detail sumber perubahan (mutasi/opname) +- History user yang melakukan aksi +- Catatan dan keterangan perubahan + +### 4. Export Data + +- Export ke Excel +- Export ke PDF +- Data yang diekspor dapat disesuaikan + +## Jenis Perubahan Stock + +### 1. Penambahan (Increase) + +- Stock bertambah dari transaksi +- Biasanya dari mutasi masuk atau opname correction + +### 2. Pengurangan (Decrease) + +- Stock berkurang dari transaksi +- Biasanya dari mutasi keluar atau penjualan + +### 3. Penyesuaian (Adjustment) + +- Penyesuaian stock dari opname +- Koreksi stock manual + +### 4. Tidak Ada Perubahan (No Change) + +- Record dibuat tapi tidak ada perubahan quantity +- Biasanya untuk tracking purpose + +## Cara Menggunakan + +### 1. Akses Menu + +``` +Warehouse -> Stock Audit +``` + +### 2. Menggunakan Filter + +```javascript +// Filter dealer +$("#filter-dealer").val("Nama Dealer"); + +// Filter produk +$("#filter-product").val("Nama Produk"); + +// Filter jenis perubahan +$("#filter-change-type").val("increase"); // increase, decrease, adjustment, no_change + +// Filter tanggal +$("#filter-date").val("2024-01-15"); + +// Reset semua filter +$("#reset-filters").click(); +``` + +### 3. Melihat Detail + +```javascript +// Klik tombol Detail pada baris data +showAuditDetail(stockLogId); +``` + +## Setup dan Instalasi + +### 1. Setup Menu dan Privileges + +```bash +php artisan setup:stock-audit-menu +``` + +### 2. Atau Menggunakan Seeder + +```bash +php artisan db:seed --class=StockAuditMenuSeeder +``` + +## Struktur Data + +### Model yang Terlibat + +- **StockLog**: Record audit perubahan stock +- **Stock**: Data stock utama +- **Product**: Data produk +- **Dealer**: Data dealer +- **User**: Data user +- **Mutation**: Data mutasi stock +- **StockOpname**: Data opname stock + +### Relasi Database + +```php +StockLog belongsTo Stock +StockLog belongsTo User +StockLog morphTo Source (Mutation, StockOpname, etc) +Stock belongsTo Product +Stock belongsTo Dealer +``` + +## API Endpoints + +### 1. Index (List Data) + +``` +GET /warehouse/stock-audit +``` + +### 2. Detail Audit + +``` +GET /warehouse/stock-audit/{stockLog}/detail +``` + +## Kustomisasi + +### 1. Menambah Jenis Perubahan + +Edit enum `StockChangeType`: + +```php +// app/Enums/StockChangeType.php +case NEW_TYPE = 'new_type'; + +public function label(): string +{ + return match($this) { + // ... existing cases + self::NEW_TYPE => 'Label Baru', + }; +} +``` + +### 2. Menambah Filter Custom + +Edit controller dan view untuk menambah filter baru: + +```php +// Controller +->filterColumn('new_field', function($query, $keyword) { + $query->where('new_field', 'like', "%{$keyword}%"); +}) + +// View + +``` + +### 3. Kustomisasi Export + +Edit DataTables buttons untuk menyesuaikan kolom export: + +```javascript +exportOptions: { + columns: [1, 2, 3, 4, 5, 6, 7, 8]; // Sesuaikan kolom yang ingin diekspor +} +``` + +## Troubleshooting + +### 1. Menu Tidak Muncul + +- Pastikan menu sudah di-setup dengan benar +- Cek privileges user untuk menu stock-audit.index +- Cek role user memiliki akses view = 1 + +### 2. Data Tidak Muncul + +- Cek apakah ada data StockLog di database +- Cek filter yang aktive +- Cek permission user untuk melihat data dealer tertentu + +### 3. Detail Tidak Loading + +- Cek URL endpoint `/warehouse/stock-audit/{id}/detail` +- Cek network tab di browser untuk error response +- Cek log Laravel untuk error detail + +## Keamanan + +### 1. Filter Berdasarkan Role + +- User dengan `dealer_id` hanya melihat data dealer mereka +- Admin dapat melihat semua data + +### 2. View-Only Access + +- Menu ini adalah read-only +- Tidak ada aksi create, update, atau delete +- Hanya viewing dan export yang diizinkan + +### 3. Audit Trail + +- Setiap akses audit log dapat di-track +- User activity dapat dimonitor +- Data tidak dapat dimanipulasi + +## Performance Tips + +### 1. Index Database + +Pastikan ada index pada kolom yang sering difilter: + +```sql +-- Index untuk performance +CREATE INDEX idx_stock_logs_created_at ON stock_logs(created_at); +CREATE INDEX idx_stock_logs_change_type ON stock_logs(change_type); +CREATE INDEX idx_stock_logs_stock_id ON stock_logs(stock_id); +``` + +### 2. Pagination + +- DataTables menggunakan server-side processing +- Default page length: 25 records +- Dapat disesuaikan sesuai kebutuhan + +### 3. Caching + +Jika data sangat besar, pertimbangkan untuk menambah caching: + +```php +// Cache dealer dan product data +$dealers = Cache::remember('dealers_for_audit', 3600, function () { + return Dealer::all(); +}); +``` diff --git a/public/js/warehouse_management/mutations/index.js.map b/public/js/warehouse_management/mutations/index.js.map index 701b3f9..97902f5 100755 --- a/public/js/warehouse_management/mutations/index.js.map +++ b/public/js/warehouse_management/mutations/index.js.map @@ -1 +1 @@ -{"version":3,"file":"/js/warehouse_management/mutations/index.js","mappings":"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","sources":["webpack:///./resources/js/warehouse_management/mutations/index.js"],"sourcesContent":["$(document).ready(function () {\n console.log(\"Mutations index.js loaded\");\n\n // Check if DataTables is available\n if (typeof $.fn.DataTable === \"undefined\") {\n console.error(\"DataTables not available!\");\n return;\n }\n\n // Destroy existing table if any\n if ($.fn.DataTable.isDataTable(\"#mutations-table\")) {\n $(\"#mutations-table\").DataTable().destroy();\n }\n\n // Initialize DataTable\n var table = $(\"#mutations-table\").DataTable({\n processing: true,\n serverSide: true,\n destroy: true,\n ajax: {\n url: $(\"#mutations-table\").data(\"url\"),\n type: \"GET\",\n error: function (xhr, error, code) {\n console.error(\"DataTables AJAX error:\", error, code);\n },\n },\n columnDefs: [\n {\n targets: 0, // No. column\n orderable: false,\n searchable: false,\n width: \"5%\",\n },\n {\n targets: [1, 2, 3, 4, 5, 6, 7], // All sortable columns\n orderable: true,\n searchable: true,\n },\n {\n targets: 8, // Action column\n orderable: false,\n searchable: false,\n width: \"20%\",\n className: \"text-center\",\n },\n {\n targets: [6, 7], // Total Items and Status columns\n className: \"text-center\",\n },\n ],\n columns: [\n {\n data: \"DT_RowIndex\",\n name: \"DT_RowIndex\",\n },\n {\n data: \"mutation_number\",\n name: \"mutation_number\",\n },\n {\n data: \"created_at\",\n name: \"created_at\",\n },\n {\n data: \"from_dealer\",\n name: \"fromDealer.name\",\n },\n {\n data: \"to_dealer\",\n name: \"toDealer.name\",\n },\n {\n data: \"requested_by\",\n name: \"requestedBy.name\",\n },\n {\n data: \"total_items\",\n name: \"total_items\",\n },\n {\n data: \"status\",\n name: \"status\",\n },\n {\n data: \"action\",\n name: \"action\",\n },\n ],\n order: [[2, \"desc\"]],\n pageLength: 10,\n responsive: true,\n });\n\n // Handle Cancel Button Click with SweetAlert\n $(document).on(\"click\", \".btn-cancel\", function () {\n var mutationId = $(this).data(\"id\");\n\n if (typeof Swal !== \"undefined\") {\n Swal.fire({\n title: \"Batalkan Mutasi?\",\n text: \"Apakah Anda yakin ingin membatalkan mutasi ini?\",\n icon: \"warning\",\n showCancelButton: true,\n confirmButtonColor: \"#d33\",\n cancelButtonColor: \"#3085d6\",\n confirmButtonText: \"Ya, Batalkan\",\n cancelButtonText: \"Batal\",\n }).then((result) => {\n if (result.isConfirmed) {\n cancelMutation(mutationId);\n }\n });\n } else {\n if (confirm(\"Apakah Anda yakin ingin membatalkan mutasi ini?\")) {\n cancelMutation(mutationId);\n }\n }\n });\n\n function cancelMutation(mutationId) {\n $.ajax({\n url: \"/warehouse/mutations/\" + mutationId + \"/cancel\",\n type: \"POST\",\n data: {\n _token: $('meta[name=\"csrf-token\"]').attr(\"content\"),\n },\n success: function (response) {\n if (typeof Swal !== \"undefined\") {\n Swal.fire({\n title: \"Berhasil!\",\n text: \"Mutasi berhasil dibatalkan\",\n icon: \"success\",\n timer: 2000,\n showConfirmButton: false,\n });\n } else {\n alert(\"Mutasi berhasil dibatalkan\");\n }\n table.ajax.reload();\n },\n error: function (xhr) {\n var errorMsg =\n xhr.responseJSON?.message || \"Gagal membatalkan mutasi\";\n if (typeof Swal !== \"undefined\") {\n Swal.fire({\n title: \"Error!\",\n text: errorMsg,\n icon: \"error\",\n });\n } else {\n alert(\"Error: \" + errorMsg);\n }\n },\n });\n }\n\n // Handle form submissions with loading state\n $(document).on(\"submit\", \".approve-form\", function () {\n $(this)\n .find('button[type=\"submit\"]')\n .prop(\"disabled\", true)\n .html(\"Memproses...\");\n });\n\n // Validate quantity approved in receive modal\n $(document).on(\"input\", 'input[name*=\"quantity_approved\"]', function () {\n var maxValue = parseFloat($(this).attr(\"max\"));\n var currentValue = parseFloat($(this).val());\n\n if (maxValue && currentValue > maxValue) {\n $(this).val(maxValue);\n $(this).addClass(\"is-invalid\");\n if (!$(this).siblings(\".invalid-feedback\").length) {\n $(this).after(\n '
Quantity tidak boleh melebihi yang diminta
'\n );\n }\n } else {\n $(this).removeClass(\"is-invalid\");\n $(this).siblings(\".invalid-feedback\").remove();\n }\n });\n});\n"],"names":["$","document","ready","console","log","fn","DataTable","isDataTable","destroy","table","processing","serverSide","ajax","url","data","type","error","xhr","code","columnDefs","targets","orderable","searchable","width","className","columns","name","order","pageLength","responsive","on","mutationId","this","Swal","fire","title","text","icon","showCancelButton","confirmButtonColor","cancelButtonColor","confirmButtonText","cancelButtonText","then","result","isConfirmed","cancelMutation","confirm","find","prop","html","maxValue","parseFloat","attr","currentValue","val","addClass","siblings","length","after","removeClass","remove","_token","success","response","timer","showConfirmButton","alert","reload","errorMsg","responseJSON","message"],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"/js/warehouse_management/mutations/index.js","mappings":"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","sources":["webpack:///./resources/js/warehouse_management/mutations/index.js"],"sourcesContent":["$(document).ready(function () {\n console.log(\"Mutations index.js loaded\");\n\n // Check if DataTables is available\n if (typeof $.fn.DataTable === \"undefined\") {\n console.error(\"DataTables not available!\");\n return;\n }\n\n // Destroy existing table if any\n if ($.fn.DataTable.isDataTable(\"#mutations-table\")) {\n $(\"#mutations-table\").DataTable().destroy();\n }\n\n // Initialize DataTable\n var table = $(\"#mutations-table\").DataTable({\n processing: true,\n serverSide: true,\n destroy: true,\n ajax: {\n url: $(\"#mutations-table\").data(\"url\"),\n type: \"GET\",\n error: function (xhr, error, code) {\n console.error(\"DataTables AJAX error:\", error, code);\n },\n },\n columnDefs: [\n {\n targets: 0, // No. column\n orderable: false,\n searchable: false,\n width: \"5%\",\n },\n {\n targets: [1, 2, 3, 4, 5, 6, 7], // All sortable columns\n orderable: true,\n searchable: true,\n },\n {\n targets: 8, // Action column\n orderable: false,\n searchable: false,\n width: \"20%\",\n className: \"text-center\",\n },\n {\n targets: [6, 7], // Total Items and Status columns\n className: \"text-center\",\n },\n ],\n columns: [\n {\n data: \"DT_RowIndex\",\n name: \"DT_RowIndex\",\n },\n {\n data: \"mutation_number\",\n name: \"mutation_number\",\n },\n {\n data: \"created_at\",\n name: \"created_at\",\n },\n {\n data: \"from_dealer\",\n name: \"fromDealer.name\",\n },\n {\n data: \"to_dealer\",\n name: \"toDealer.name\",\n },\n {\n data: \"requested_by\",\n name: \"requestedBy.name\",\n },\n {\n data: \"total_items\",\n name: \"total_items\",\n },\n {\n data: \"status\",\n name: \"status\",\n },\n {\n data: \"action\",\n name: \"action\",\n },\n ],\n order: [[1, \"desc\"]], // Order by mutation_number desc (which follows ID order)\n pageLength: 10,\n responsive: true,\n });\n\n // Handle Cancel Button Click with SweetAlert\n $(document).on(\"click\", \".btn-cancel\", function () {\n var mutationId = $(this).data(\"id\");\n\n if (typeof Swal !== \"undefined\") {\n Swal.fire({\n title: \"Batalkan Mutasi?\",\n text: \"Apakah Anda yakin ingin membatalkan mutasi ini?\",\n icon: \"warning\",\n showCancelButton: true,\n confirmButtonColor: \"#d33\",\n cancelButtonColor: \"#3085d6\",\n confirmButtonText: \"Ya, Batalkan\",\n cancelButtonText: \"Batal\",\n }).then((result) => {\n if (result.isConfirmed) {\n cancelMutation(mutationId);\n }\n });\n } else {\n if (confirm(\"Apakah Anda yakin ingin membatalkan mutasi ini?\")) {\n cancelMutation(mutationId);\n }\n }\n });\n\n function cancelMutation(mutationId) {\n $.ajax({\n url: \"/warehouse/mutations/\" + mutationId + \"/cancel\",\n type: \"POST\",\n data: {\n _token: $('meta[name=\"csrf-token\"]').attr(\"content\"),\n },\n success: function (response) {\n if (typeof Swal !== \"undefined\") {\n Swal.fire({\n title: \"Berhasil!\",\n text: \"Mutasi berhasil dibatalkan\",\n icon: \"success\",\n timer: 2000,\n showConfirmButton: false,\n });\n } else {\n alert(\"Mutasi berhasil dibatalkan\");\n }\n table.ajax.reload();\n },\n error: function (xhr) {\n var errorMsg =\n xhr.responseJSON?.message || \"Gagal membatalkan mutasi\";\n if (typeof Swal !== \"undefined\") {\n Swal.fire({\n title: \"Error!\",\n text: errorMsg,\n icon: \"error\",\n });\n } else {\n alert(\"Error: \" + errorMsg);\n }\n },\n });\n }\n\n // Handle form submissions with loading state\n $(document).on(\"submit\", \".approve-form\", function () {\n $(this)\n .find('button[type=\"submit\"]')\n .prop(\"disabled\", true)\n .html(\"Memproses...\");\n });\n\n // Validate quantity approved in receive modal\n $(document).on(\"input\", 'input[name*=\"quantity_approved\"]', function () {\n var maxValue = parseFloat($(this).attr(\"max\"));\n var currentValue = parseFloat($(this).val());\n\n if (maxValue && currentValue > maxValue) {\n $(this).val(maxValue);\n $(this).addClass(\"is-invalid\");\n if (!$(this).siblings(\".invalid-feedback\").length) {\n $(this).after(\n '
Quantity tidak boleh melebihi yang diminta
'\n );\n }\n } else {\n $(this).removeClass(\"is-invalid\");\n $(this).siblings(\".invalid-feedback\").remove();\n }\n });\n});\n"],"names":["$","document","ready","console","log","fn","DataTable","isDataTable","destroy","table","processing","serverSide","ajax","url","data","type","error","xhr","code","columnDefs","targets","orderable","searchable","width","className","columns","name","order","pageLength","responsive","on","mutationId","this","Swal","fire","title","text","icon","showCancelButton","confirmButtonColor","cancelButtonColor","confirmButtonText","cancelButtonText","then","result","isConfirmed","cancelMutation","confirm","find","prop","html","maxValue","parseFloat","attr","currentValue","val","addClass","siblings","length","after","removeClass","remove","_token","success","response","timer","showConfirmButton","alert","reload","errorMsg","responseJSON","message"],"sourceRoot":""} \ No newline at end of file diff --git a/public/js/warehouse_management/stock_audit/index.js b/public/js/warehouse_management/stock_audit/index.js new file mode 100644 index 0000000..cb6cafe --- /dev/null +++ b/public/js/warehouse_management/stock_audit/index.js @@ -0,0 +1,32 @@ +/* + * ATTENTION: An "eval-source-map" devtool has been used. + * This devtool is neither made for production nor for readable output files. + * It uses "eval()" calls to create a separate source file with attached SourceMaps in the browser devtools. + * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) + * or disable the default devtool with "devtool: false". + * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). + */ +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({ + +/***/ "./resources/js/warehouse_management/stock_audit/index.js": +/*!****************************************************************!*\ + !*** ./resources/js/warehouse_management/stock_audit/index.js ***! + \****************************************************************/ +/***/ (() => { + +eval("console.log(\"Stock audit JS loaded\"); // Helper function to format date\n\nfunction formatDate(dateString) {\n if (!dateString) return \"-\";\n var date = new Date(dateString);\n var months = [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"Mei\", \"Jun\", \"Jul\", \"Agu\", \"Sep\", \"Okt\", \"Nov\", \"Des\"];\n var day = date.getDate().toString().padStart(2, \"0\");\n var month = months[date.getMonth()];\n var year = date.getFullYear();\n var hours = date.getHours().toString().padStart(2, \"0\");\n var minutes = date.getMinutes().toString().padStart(2, \"0\");\n return \"\".concat(day, \" \").concat(month, \" \").concat(year, \", \").concat(hours, \":\").concat(minutes);\n}\n\n$(document).ready(function () {\n console.log(\"Initializing stock audit table...\"); // Initialize Select2 without any event handlers\n\n $(\".select2\").select2({\n placeholder: \"Pilih...\",\n allowClear: true,\n width: \"100%\"\n }); // Initialize Datepicker\n\n $(\".datepicker\").datepicker({\n format: \"yyyy-mm-dd\",\n autoclose: true,\n todayHighlight: true,\n orientation: \"bottom auto\",\n language: \"id\",\n clearBtn: true,\n container: \"body\"\n });\n var $table = $(\"#stock-audit-table\");\n var indexRoute = $table.data(\"route\");\n console.log(\"Table route:\", indexRoute);\n var table = $table.DataTable({\n processing: true,\n serverSide: true,\n language: {\n processing: '
Memproses...
',\n loadingRecords: \"Memuat data...\",\n zeroRecords: \"Tidak ada data yang ditemukan\",\n emptyTable: \"Tidak ada data tersedia\"\n },\n ajax: {\n url: indexRoute,\n data: function data(d) {\n d.dealer = $(\"#filter-dealer\").val();\n d.product = $(\"#filter-product\").val();\n d.change_type = $(\"#filter-change-type\").val();\n d.date = $(\"#filter-date\").val();\n console.log(\"Ajax data with ordering:\", d);\n console.log(\"Order info:\", d.order);\n console.log(\"Columns info:\", d.columns);\n },\n error: function error(xhr, _error, thrown) {\n console.error(\"Ajax error:\", _error);\n console.error(\"Response:\", xhr.responseText);\n }\n },\n columns: [{\n data: \"DT_RowIndex\",\n name: \"DT_RowIndex\",\n orderable: false,\n searchable: false,\n width: \"5%\"\n }, {\n data: \"product_name\",\n name: \"product_name\",\n orderable: true\n }, {\n data: \"dealer_name\",\n name: \"dealer_name\",\n orderable: true\n }, {\n data: \"change_type\",\n name: \"change_type\",\n orderable: true\n }, {\n data: \"quantity_change\",\n name: \"quantity_change\",\n className: \"text-center\",\n orderable: true\n }, {\n data: \"stock_before_after\",\n name: \"stock_before_after\",\n className: \"text-center\",\n orderable: true\n }, {\n data: \"source_info\",\n name: \"source_info\",\n orderable: true\n }, {\n data: \"user_name\",\n name: \"user_name\",\n orderable: true\n }, {\n data: \"created_at\",\n name: \"created_at\",\n orderable: true\n }, {\n data: \"action\",\n name: \"action\",\n orderable: false,\n searchable: false,\n width: \"10%\"\n }],\n order: [[8, \"desc\"]],\n // Order by created_at desc (column index 8)\n pageLength: 25,\n responsive: true,\n ordering: true,\n // Enable column ordering\n orderMulti: false // Single column ordering only\n\n });\n console.log(\"Table initialized:\", table); // Add loading indicator for ordering\n\n table.on(\"processing.dt\", function (e, settings, processing) {\n if (processing) {\n console.log(\"DataTable processing started (ordering/filtering)\");\n } else {\n console.log(\"DataTable processing finished\");\n }\n }); // Debug order events\n\n table.on(\"order.dt\", function () {\n console.log(\"Order changed:\", table.order());\n }); // Manual modal close handlers\n\n $(document).on(\"click\", \"#modal-close-btn, #modal-close-footer-btn\", function () {\n console.log(\"Manual close button clicked\");\n $(\"#auditDetailModal\").modal(\"hide\");\n }); // Modal backdrop click handler\n\n $(document).on(\"click\", \"#auditDetailModal\", function (e) {\n if (e.target === this) {\n console.log(\"Modal backdrop clicked\");\n $(\"#auditDetailModal\").modal(\"hide\");\n }\n }); // ESC key handler\n\n $(document).on(\"keydown\", function (e) {\n if (e.keyCode === 27 && $(\"#auditDetailModal\").hasClass(\"show\")) {\n console.log(\"ESC key pressed\");\n $(\"#auditDetailModal\").modal(\"hide\");\n }\n }); // Modal hidden event handler\n\n $(\"#auditDetailModal\").on(\"hidden.bs.modal\", function () {\n console.log(\"Modal hidden\"); // Reset modal content\n\n $(\"#modal-loading\").show();\n $(\"#modal-error\").hide();\n $(\"#modal-content\").hide();\n }); // Apply filters button - only way to trigger table reload\n\n $(\"#apply-filters\").click(function () {\n console.log(\"Apply filters clicked, reloading table...\");\n console.log(\"Current filter values:\", {\n dealer: $(\"#filter-dealer\").val(),\n product: $(\"#filter-product\").val(),\n change_type: $(\"#filter-change-type\").val(),\n date: $(\"#filter-date\").val()\n });\n table.ajax.reload();\n }); // Allow Enter key to apply filters on datepicker\n\n $(\"#filter-date\").keypress(function (e) {\n if (e.which == 13) {\n // Enter key\n console.log(\"Enter pressed on date filter, applying filters...\");\n table.ajax.reload();\n }\n }); // Reset filters\n\n $(\"#reset-filters\").click(function () {\n console.log(\"Resetting filters...\"); // Reset select2 elements properly\n\n $(\"#filter-dealer\").val(null).trigger(\"change.select2\");\n $(\"#filter-product\").val(null).trigger(\"change.select2\");\n $(\"#filter-change-type\").val(null).trigger(\"change.select2\"); // Reset datepicker properly\n\n $(\"#filter-date\").val(\"\").datepicker(\"update\");\n console.log(\"Filters reset, values after reset:\", {\n dealer: $(\"#filter-dealer\").val(),\n product: $(\"#filter-product\").val(),\n change_type: $(\"#filter-change-type\").val(),\n date: $(\"#filter-date\").val()\n }); // Reload table after reset\n\n console.log(\"Reloading table after reset...\");\n table.ajax.reload();\n });\n});\n\nwindow.showAuditDetail = function (id) {\n console.log(\"Showing audit detail for ID:\", id); // Reset modal states first\n\n $(\"#modal-loading\").show();\n $(\"#modal-error\").hide();\n $(\"#modal-content\").hide(); // Show modal\n\n $(\"#auditDetailModal\").modal(\"show\");\n $.ajax({\n url: \"/warehouse/stock-audit/\".concat(id, \"/detail\"),\n method: \"GET\",\n success: function success(response) {\n console.log(\"Detail response:\", response);\n $(\"#modal-loading\").hide();\n\n if (response.success) {\n populateModalContent(response.data, response.source_detail);\n $(\"#modal-content\").show();\n } else {\n $(\"#error-message\").text(response.message);\n $(\"#modal-error\").show();\n }\n },\n error: function error(xhr) {\n console.error(\"Detail AJAX error:\", xhr);\n $(\"#modal-loading\").hide();\n $(\"#error-message\").text(\"Gagal memuat detail audit\");\n $(\"#modal-error\").show();\n }\n });\n};\n\nfunction populateModalContent(audit, sourceDetail) {\n console.log(\"Populating modal content:\", audit); // Populate basic stock information\n\n $(\"#product-name\").text(audit.stock.product.name);\n $(\"#dealer-name\").text(audit.stock.dealer.name);\n $(\"#previous-quantity\").text(audit.previous_quantity);\n $(\"#new-quantity\").text(audit.new_quantity);\n $(\"#user-name\").text(audit.user ? audit.user.name : \"-\");\n $(\"#created-at\").text(audit.created_at_formatted);\n $(\"#description\").text(audit.description || \"-\"); // Set quantity change with styling\n\n var quantityChangeClass = \"\";\n var quantityChangeSign = \"\";\n\n if (audit.quantity_change > 0) {\n quantityChangeClass = \"text-success\";\n quantityChangeSign = \"+\";\n } else if (audit.quantity_change < 0) {\n quantityChangeClass = \"text-danger\";\n quantityChangeSign = \"\";\n } else {\n quantityChangeClass = \"text-muted\";\n quantityChangeSign = \"\";\n }\n\n $(\"#quantity-change\").html(\"\").concat(quantityChangeSign).concat(audit.quantity_change, \"\")); // Set change type with styling\n\n var changeTypeClass = \"\";\n\n switch (audit.change_type) {\n case \"increase\":\n changeTypeClass = \"text-success\";\n break;\n\n case \"decrease\":\n changeTypeClass = \"text-danger\";\n break;\n\n case \"adjustment\":\n changeTypeClass = \"text-warning\";\n break;\n\n default:\n changeTypeClass = \"text-muted\";\n }\n\n $(\"#change-type\").html(\"\").concat(audit.change_type_label, \"\")); // Handle source detail\n\n if (sourceDetail) {\n $(\"#source-detail\").show();\n\n if (sourceDetail.type === \"mutation\") {\n var mutation = sourceDetail.data;\n $(\"#source-title\").text(\"Mutasi Stock: \".concat(mutation.mutation_number));\n var mutationContent = \"\\n
\\n
\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
Dari Dealer:\".concat(mutation.from_dealer ? mutation.from_dealer.name : \"-\", \"
Ke Dealer:\").concat(mutation.to_dealer ? mutation.to_dealer.name : \"-\", \"
Status:\").concat(mutation.status, \"
\\n
\\n
\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
Diminta oleh:\").concat(mutation.requested_by ? mutation.requested_by.name : \"-\", \"
Disetujui oleh:\").concat(mutation.approved_by ? mutation.approved_by.name : \"-\", \"
Tanggal Disetujui:\").concat(mutation.approved_at_formatted || \"-\", \"
\\n
\\n
\\n \");\n $(\"#source-content\").html(mutationContent);\n } else if (sourceDetail.type === \"opname\") {\n var opname = sourceDetail.data;\n $(\"#source-title\").text(\"Opname\");\n var opnameContent = \"\\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n \\n
Dealer:\".concat(opname.dealer ? opname.dealer.name : \"-\", \"
User:\").concat(opname.user ? opname.user.name : \"-\", \"
Status:\").concat(opname.status || \"-\", \"
\\n \");\n $(\"#source-content\").html(opnameContent);\n }\n } else {\n $(\"#source-detail\").hide();\n }\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvc3RvY2tfYXVkaXQvaW5kZXguanMiLCJuYW1lcyI6WyJjb25zb2xlIiwibG9nIiwiZm9ybWF0RGF0ZSIsImRhdGVTdHJpbmciLCJkYXRlIiwiRGF0ZSIsIm1vbnRocyIsImRheSIsImdldERhdGUiLCJ0b1N0cmluZyIsInBhZFN0YXJ0IiwibW9udGgiLCJnZXRNb250aCIsInllYXIiLCJnZXRGdWxsWWVhciIsImhvdXJzIiwiZ2V0SG91cnMiLCJtaW51dGVzIiwiZ2V0TWludXRlcyIsIiQiLCJkb2N1bWVudCIsInJlYWR5Iiwic2VsZWN0MiIsInBsYWNlaG9sZGVyIiwiYWxsb3dDbGVhciIsIndpZHRoIiwiZGF0ZXBpY2tlciIsImZvcm1hdCIsImF1dG9jbG9zZSIsInRvZGF5SGlnaGxpZ2h0Iiwib3JpZW50YXRpb24iLCJsYW5ndWFnZSIsImNsZWFyQnRuIiwiY29udGFpbmVyIiwiJHRhYmxlIiwiaW5kZXhSb3V0ZSIsImRhdGEiLCJ0YWJsZSIsIkRhdGFUYWJsZSIsInByb2Nlc3NpbmciLCJzZXJ2ZXJTaWRlIiwibG9hZGluZ1JlY29yZHMiLCJ6ZXJvUmVjb3JkcyIsImVtcHR5VGFibGUiLCJhamF4IiwidXJsIiwiZCIsImRlYWxlciIsInZhbCIsInByb2R1Y3QiLCJjaGFuZ2VfdHlwZSIsIm9yZGVyIiwiY29sdW1ucyIsImVycm9yIiwieGhyIiwidGhyb3duIiwicmVzcG9uc2VUZXh0IiwibmFtZSIsIm9yZGVyYWJsZSIsInNlYXJjaGFibGUiLCJjbGFzc05hbWUiLCJwYWdlTGVuZ3RoIiwicmVzcG9uc2l2ZSIsIm9yZGVyaW5nIiwib3JkZXJNdWx0aSIsIm9uIiwiZSIsInNldHRpbmdzIiwibW9kYWwiLCJ0YXJnZXQiLCJrZXlDb2RlIiwiaGFzQ2xhc3MiLCJzaG93IiwiaGlkZSIsImNsaWNrIiwicmVsb2FkIiwia2V5cHJlc3MiLCJ3aGljaCIsInRyaWdnZXIiLCJ3aW5kb3ciLCJzaG93QXVkaXREZXRhaWwiLCJpZCIsIm1ldGhvZCIsInN1Y2Nlc3MiLCJyZXNwb25zZSIsInBvcHVsYXRlTW9kYWxDb250ZW50Iiwic291cmNlX2RldGFpbCIsInRleHQiLCJtZXNzYWdlIiwiYXVkaXQiLCJzb3VyY2VEZXRhaWwiLCJzdG9jayIsInByZXZpb3VzX3F1YW50aXR5IiwibmV3X3F1YW50aXR5IiwidXNlciIsImNyZWF0ZWRfYXRfZm9ybWF0dGVkIiwiZGVzY3JpcHRpb24iLCJxdWFudGl0eUNoYW5nZUNsYXNzIiwicXVhbnRpdHlDaGFuZ2VTaWduIiwicXVhbnRpdHlfY2hhbmdlIiwiaHRtbCIsImNoYW5nZVR5cGVDbGFzcyIsImNoYW5nZV90eXBlX2xhYmVsIiwidHlwZSIsIm11dGF0aW9uIiwibXV0YXRpb25fbnVtYmVyIiwibXV0YXRpb25Db250ZW50IiwiZnJvbV9kZWFsZXIiLCJ0b19kZWFsZXIiLCJzdGF0dXMiLCJyZXF1ZXN0ZWRfYnkiLCJhcHByb3ZlZF9ieSIsImFwcHJvdmVkX2F0X2Zvcm1hdHRlZCIsIm9wbmFtZSIsIm9wbmFtZUNvbnRlbnQiXSwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL3Jlc291cmNlcy9qcy93YXJlaG91c2VfbWFuYWdlbWVudC9zdG9ja19hdWRpdC9pbmRleC5qcz9kNTBhIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnNvbGUubG9nKFwiU3RvY2sgYXVkaXQgSlMgbG9hZGVkXCIpO1xuXG4vLyBIZWxwZXIgZnVuY3Rpb24gdG8gZm9ybWF0IGRhdGVcbmZ1bmN0aW9uIGZvcm1hdERhdGUoZGF0ZVN0cmluZykge1xuICAgIGlmICghZGF0ZVN0cmluZykgcmV0dXJuIFwiLVwiO1xuXG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKGRhdGVTdHJpbmcpO1xuICAgIGNvbnN0IG1vbnRocyA9IFtcbiAgICAgICAgXCJKYW5cIixcbiAgICAgICAgXCJGZWJcIixcbiAgICAgICAgXCJNYXJcIixcbiAgICAgICAgXCJBcHJcIixcbiAgICAgICAgXCJNZWlcIixcbiAgICAgICAgXCJKdW5cIixcbiAgICAgICAgXCJKdWxcIixcbiAgICAgICAgXCJBZ3VcIixcbiAgICAgICAgXCJTZXBcIixcbiAgICAgICAgXCJPa3RcIixcbiAgICAgICAgXCJOb3ZcIixcbiAgICAgICAgXCJEZXNcIixcbiAgICBdO1xuXG4gICAgY29uc3QgZGF5ID0gZGF0ZS5nZXREYXRlKCkudG9TdHJpbmcoKS5wYWRTdGFydCgyLCBcIjBcIik7XG4gICAgY29uc3QgbW9udGggPSBtb250aHNbZGF0ZS5nZXRNb250aCgpXTtcbiAgICBjb25zdCB5ZWFyID0gZGF0ZS5nZXRGdWxsWWVhcigpO1xuICAgIGNvbnN0IGhvdXJzID0gZGF0ZS5nZXRIb3VycygpLnRvU3RyaW5nKCkucGFkU3RhcnQoMiwgXCIwXCIpO1xuICAgIGNvbnN0IG1pbnV0ZXMgPSBkYXRlLmdldE1pbnV0ZXMoKS50b1N0cmluZygpLnBhZFN0YXJ0KDIsIFwiMFwiKTtcblxuICAgIHJldHVybiBgJHtkYXl9ICR7bW9udGh9ICR7eWVhcn0sICR7aG91cnN9OiR7bWludXRlc31gO1xufVxuXG4kKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbiAoKSB7XG4gICAgY29uc29sZS5sb2coXCJJbml0aWFsaXppbmcgc3RvY2sgYXVkaXQgdGFibGUuLi5cIik7XG5cbiAgICAvLyBJbml0aWFsaXplIFNlbGVjdDIgd2l0aG91dCBhbnkgZXZlbnQgaGFuZGxlcnNcbiAgICAkKFwiLnNlbGVjdDJcIikuc2VsZWN0Mih7XG4gICAgICAgIHBsYWNlaG9sZGVyOiBcIlBpbGloLi4uXCIsXG4gICAgICAgIGFsbG93Q2xlYXI6IHRydWUsXG4gICAgICAgIHdpZHRoOiBcIjEwMCVcIixcbiAgICB9KTtcblxuICAgIC8vIEluaXRpYWxpemUgRGF0ZXBpY2tlclxuICAgICQoXCIuZGF0ZXBpY2tlclwiKS5kYXRlcGlja2VyKHtcbiAgICAgICAgZm9ybWF0OiBcInl5eXktbW0tZGRcIixcbiAgICAgICAgYXV0b2Nsb3NlOiB0cnVlLFxuICAgICAgICB0b2RheUhpZ2hsaWdodDogdHJ1ZSxcbiAgICAgICAgb3JpZW50YXRpb246IFwiYm90dG9tIGF1dG9cIixcbiAgICAgICAgbGFuZ3VhZ2U6IFwiaWRcIixcbiAgICAgICAgY2xlYXJCdG46IHRydWUsXG4gICAgICAgIGNvbnRhaW5lcjogXCJib2R5XCIsXG4gICAgfSk7XG5cbiAgICBjb25zdCAkdGFibGUgPSAkKFwiI3N0b2NrLWF1ZGl0LXRhYmxlXCIpO1xuICAgIGNvbnN0IGluZGV4Um91dGUgPSAkdGFibGUuZGF0YShcInJvdXRlXCIpO1xuXG4gICAgY29uc29sZS5sb2coXCJUYWJsZSByb3V0ZTpcIiwgaW5kZXhSb3V0ZSk7XG5cbiAgICBsZXQgdGFibGUgPSAkdGFibGUuRGF0YVRhYmxlKHtcbiAgICAgICAgcHJvY2Vzc2luZzogdHJ1ZSxcbiAgICAgICAgc2VydmVyU2lkZTogdHJ1ZSxcbiAgICAgICAgbGFuZ3VhZ2U6IHtcbiAgICAgICAgICAgIHByb2Nlc3Npbmc6XG4gICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWNlbnRlclwiPjxkaXYgY2xhc3M9XCJzcGlubmVyLWJvcmRlciB0ZXh0LXByaW1hcnlcIiByb2xlPVwic3RhdHVzXCI+PHNwYW4gY2xhc3M9XCJzci1vbmx5XCI+TWVtcHJvc2VzLi4uPC9zcGFuPjwvZGl2PjwvZGl2PicsXG4gICAgICAgICAgICBsb2FkaW5nUmVjb3JkczogXCJNZW11YXQgZGF0YS4uLlwiLFxuICAgICAgICAgICAgemVyb1JlY29yZHM6IFwiVGlkYWsgYWRhIGRhdGEgeWFuZyBkaXRlbXVrYW5cIixcbiAgICAgICAgICAgIGVtcHR5VGFibGU6IFwiVGlkYWsgYWRhIGRhdGEgdGVyc2VkaWFcIixcbiAgICAgICAgfSxcbiAgICAgICAgYWpheDoge1xuICAgICAgICAgICAgdXJsOiBpbmRleFJvdXRlLFxuICAgICAgICAgICAgZGF0YTogZnVuY3Rpb24gKGQpIHtcbiAgICAgICAgICAgICAgICBkLmRlYWxlciA9ICQoXCIjZmlsdGVyLWRlYWxlclwiKS52YWwoKTtcbiAgICAgICAgICAgICAgICBkLnByb2R1Y3QgPSAkKFwiI2ZpbHRlci1wcm9kdWN0XCIpLnZhbCgpO1xuICAgICAgICAgICAgICAgIGQuY2hhbmdlX3R5cGUgPSAkKFwiI2ZpbHRlci1jaGFuZ2UtdHlwZVwiKS52YWwoKTtcbiAgICAgICAgICAgICAgICBkLmRhdGUgPSAkKFwiI2ZpbHRlci1kYXRlXCIpLnZhbCgpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiQWpheCBkYXRhIHdpdGggb3JkZXJpbmc6XCIsIGQpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiT3JkZXIgaW5mbzpcIiwgZC5vcmRlcik7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJDb2x1bW5zIGluZm86XCIsIGQuY29sdW1ucyk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uICh4aHIsIGVycm9yLCB0aHJvd24pIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKFwiQWpheCBlcnJvcjpcIiwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJSZXNwb25zZTpcIiwgeGhyLnJlc3BvbnNlVGV4dCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBjb2x1bW5zOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGF0YTogXCJEVF9Sb3dJbmRleFwiLFxuICAgICAgICAgICAgICAgIG5hbWU6IFwiRFRfUm93SW5kZXhcIixcbiAgICAgICAgICAgICAgICBvcmRlcmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNlYXJjaGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHdpZHRoOiBcIjUlXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRhdGE6IFwicHJvZHVjdF9uYW1lXCIsXG4gICAgICAgICAgICAgICAgbmFtZTogXCJwcm9kdWN0X25hbWVcIixcbiAgICAgICAgICAgICAgICBvcmRlcmFibGU6IHRydWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRhdGE6IFwiZGVhbGVyX25hbWVcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBcImRlYWxlcl9uYW1lXCIsXG4gICAgICAgICAgICAgICAgb3JkZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBkYXRhOiBcImNoYW5nZV90eXBlXCIsXG4gICAgICAgICAgICAgICAgbmFtZTogXCJjaGFuZ2VfdHlwZVwiLFxuICAgICAgICAgICAgICAgIG9yZGVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGF0YTogXCJxdWFudGl0eV9jaGFuZ2VcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBcInF1YW50aXR5X2NoYW5nZVwiLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogXCJ0ZXh0LWNlbnRlclwiLFxuICAgICAgICAgICAgICAgIG9yZGVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGF0YTogXCJzdG9ja19iZWZvcmVfYWZ0ZXJcIixcbiAgICAgICAgICAgICAgICBuYW1lOiBcInN0b2NrX2JlZm9yZV9hZnRlclwiLFxuICAgICAgICAgICAgICAgIGNsYXNzTmFtZTogXCJ0ZXh0LWNlbnRlclwiLFxuICAgICAgICAgICAgICAgIG9yZGVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGF0YTogXCJzb3VyY2VfaW5mb1wiLFxuICAgICAgICAgICAgICAgIG5hbWU6IFwic291cmNlX2luZm9cIixcbiAgICAgICAgICAgICAgICBvcmRlcmFibGU6IHRydWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRhdGE6IFwidXNlcl9uYW1lXCIsXG4gICAgICAgICAgICAgICAgbmFtZTogXCJ1c2VyX25hbWVcIixcbiAgICAgICAgICAgICAgICBvcmRlcmFibGU6IHRydWUsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIGRhdGE6IFwiY3JlYXRlZF9hdFwiLFxuICAgICAgICAgICAgICAgIG5hbWU6IFwiY3JlYXRlZF9hdFwiLFxuICAgICAgICAgICAgICAgIG9yZGVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgZGF0YTogXCJhY3Rpb25cIixcbiAgICAgICAgICAgICAgICBuYW1lOiBcImFjdGlvblwiLFxuICAgICAgICAgICAgICAgIG9yZGVyYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgc2VhcmNoYWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgd2lkdGg6IFwiMTAlXCIsXG4gICAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBvcmRlcjogW1s4LCBcImRlc2NcIl1dLCAvLyBPcmRlciBieSBjcmVhdGVkX2F0IGRlc2MgKGNvbHVtbiBpbmRleCA4KVxuICAgICAgICBwYWdlTGVuZ3RoOiAyNSxcbiAgICAgICAgcmVzcG9uc2l2ZTogdHJ1ZSxcbiAgICAgICAgb3JkZXJpbmc6IHRydWUsIC8vIEVuYWJsZSBjb2x1bW4gb3JkZXJpbmdcbiAgICAgICAgb3JkZXJNdWx0aTogZmFsc2UsIC8vIFNpbmdsZSBjb2x1bW4gb3JkZXJpbmcgb25seVxuICAgIH0pO1xuXG4gICAgY29uc29sZS5sb2coXCJUYWJsZSBpbml0aWFsaXplZDpcIiwgdGFibGUpO1xuXG4gICAgLy8gQWRkIGxvYWRpbmcgaW5kaWNhdG9yIGZvciBvcmRlcmluZ1xuICAgIHRhYmxlLm9uKFwicHJvY2Vzc2luZy5kdFwiLCBmdW5jdGlvbiAoZSwgc2V0dGluZ3MsIHByb2Nlc3NpbmcpIHtcbiAgICAgICAgaWYgKHByb2Nlc3NpbmcpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRGF0YVRhYmxlIHByb2Nlc3Npbmcgc3RhcnRlZCAob3JkZXJpbmcvZmlsdGVyaW5nKVwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiRGF0YVRhYmxlIHByb2Nlc3NpbmcgZmluaXNoZWRcIik7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIERlYnVnIG9yZGVyIGV2ZW50c1xuICAgIHRhYmxlLm9uKFwib3JkZXIuZHRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICBjb25zb2xlLmxvZyhcIk9yZGVyIGNoYW5nZWQ6XCIsIHRhYmxlLm9yZGVyKCkpO1xuICAgIH0pO1xuXG4gICAgLy8gTWFudWFsIG1vZGFsIGNsb3NlIGhhbmRsZXJzXG4gICAgJChkb2N1bWVudCkub24oXG4gICAgICAgIFwiY2xpY2tcIixcbiAgICAgICAgXCIjbW9kYWwtY2xvc2UtYnRuLCAjbW9kYWwtY2xvc2UtZm9vdGVyLWJ0blwiLFxuICAgICAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIk1hbnVhbCBjbG9zZSBidXR0b24gY2xpY2tlZFwiKTtcbiAgICAgICAgICAgICQoXCIjYXVkaXREZXRhaWxNb2RhbFwiKS5tb2RhbChcImhpZGVcIik7XG4gICAgICAgIH1cbiAgICApO1xuXG4gICAgLy8gTW9kYWwgYmFja2Ryb3AgY2xpY2sgaGFuZGxlclxuICAgICQoZG9jdW1lbnQpLm9uKFwiY2xpY2tcIiwgXCIjYXVkaXREZXRhaWxNb2RhbFwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS50YXJnZXQgPT09IHRoaXMpIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiTW9kYWwgYmFja2Ryb3AgY2xpY2tlZFwiKTtcbiAgICAgICAgICAgICQoXCIjYXVkaXREZXRhaWxNb2RhbFwiKS5tb2RhbChcImhpZGVcIik7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIEVTQyBrZXkgaGFuZGxlclxuICAgICQoZG9jdW1lbnQpLm9uKFwia2V5ZG93blwiLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICBpZiAoZS5rZXlDb2RlID09PSAyNyAmJiAkKFwiI2F1ZGl0RGV0YWlsTW9kYWxcIikuaGFzQ2xhc3MoXCJzaG93XCIpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkVTQyBrZXkgcHJlc3NlZFwiKTtcbiAgICAgICAgICAgICQoXCIjYXVkaXREZXRhaWxNb2RhbFwiKS5tb2RhbChcImhpZGVcIik7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIE1vZGFsIGhpZGRlbiBldmVudCBoYW5kbGVyXG4gICAgJChcIiNhdWRpdERldGFpbE1vZGFsXCIpLm9uKFwiaGlkZGVuLmJzLm1vZGFsXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJNb2RhbCBoaWRkZW5cIik7XG4gICAgICAgIC8vIFJlc2V0IG1vZGFsIGNvbnRlbnRcbiAgICAgICAgJChcIiNtb2RhbC1sb2FkaW5nXCIpLnNob3coKTtcbiAgICAgICAgJChcIiNtb2RhbC1lcnJvclwiKS5oaWRlKCk7XG4gICAgICAgICQoXCIjbW9kYWwtY29udGVudFwiKS5oaWRlKCk7XG4gICAgfSk7XG5cbiAgICAvLyBBcHBseSBmaWx0ZXJzIGJ1dHRvbiAtIG9ubHkgd2F5IHRvIHRyaWdnZXIgdGFibGUgcmVsb2FkXG4gICAgJChcIiNhcHBseS1maWx0ZXJzXCIpLmNsaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS5sb2coXCJBcHBseSBmaWx0ZXJzIGNsaWNrZWQsIHJlbG9hZGluZyB0YWJsZS4uLlwiKTtcbiAgICAgICAgY29uc29sZS5sb2coXCJDdXJyZW50IGZpbHRlciB2YWx1ZXM6XCIsIHtcbiAgICAgICAgICAgIGRlYWxlcjogJChcIiNmaWx0ZXItZGVhbGVyXCIpLnZhbCgpLFxuICAgICAgICAgICAgcHJvZHVjdDogJChcIiNmaWx0ZXItcHJvZHVjdFwiKS52YWwoKSxcbiAgICAgICAgICAgIGNoYW5nZV90eXBlOiAkKFwiI2ZpbHRlci1jaGFuZ2UtdHlwZVwiKS52YWwoKSxcbiAgICAgICAgICAgIGRhdGU6ICQoXCIjZmlsdGVyLWRhdGVcIikudmFsKCksXG4gICAgICAgIH0pO1xuICAgICAgICB0YWJsZS5hamF4LnJlbG9hZCgpO1xuICAgIH0pO1xuXG4gICAgLy8gQWxsb3cgRW50ZXIga2V5IHRvIGFwcGx5IGZpbHRlcnMgb24gZGF0ZXBpY2tlclxuICAgICQoXCIjZmlsdGVyLWRhdGVcIikua2V5cHJlc3MoZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgaWYgKGUud2hpY2ggPT0gMTMpIHtcbiAgICAgICAgICAgIC8vIEVudGVyIGtleVxuICAgICAgICAgICAgY29uc29sZS5sb2coXCJFbnRlciBwcmVzc2VkIG9uIGRhdGUgZmlsdGVyLCBhcHBseWluZyBmaWx0ZXJzLi4uXCIpO1xuICAgICAgICAgICAgdGFibGUuYWpheC5yZWxvYWQoKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gUmVzZXQgZmlsdGVyc1xuICAgICQoXCIjcmVzZXQtZmlsdGVyc1wiKS5jbGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKFwiUmVzZXR0aW5nIGZpbHRlcnMuLi5cIik7XG5cbiAgICAgICAgLy8gUmVzZXQgc2VsZWN0MiBlbGVtZW50cyBwcm9wZXJseVxuICAgICAgICAkKFwiI2ZpbHRlci1kZWFsZXJcIikudmFsKG51bGwpLnRyaWdnZXIoXCJjaGFuZ2Uuc2VsZWN0MlwiKTtcbiAgICAgICAgJChcIiNmaWx0ZXItcHJvZHVjdFwiKS52YWwobnVsbCkudHJpZ2dlcihcImNoYW5nZS5zZWxlY3QyXCIpO1xuICAgICAgICAkKFwiI2ZpbHRlci1jaGFuZ2UtdHlwZVwiKS52YWwobnVsbCkudHJpZ2dlcihcImNoYW5nZS5zZWxlY3QyXCIpO1xuXG4gICAgICAgIC8vIFJlc2V0IGRhdGVwaWNrZXIgcHJvcGVybHlcbiAgICAgICAgJChcIiNmaWx0ZXItZGF0ZVwiKS52YWwoXCJcIikuZGF0ZXBpY2tlcihcInVwZGF0ZVwiKTtcblxuICAgICAgICBjb25zb2xlLmxvZyhcIkZpbHRlcnMgcmVzZXQsIHZhbHVlcyBhZnRlciByZXNldDpcIiwge1xuICAgICAgICAgICAgZGVhbGVyOiAkKFwiI2ZpbHRlci1kZWFsZXJcIikudmFsKCksXG4gICAgICAgICAgICBwcm9kdWN0OiAkKFwiI2ZpbHRlci1wcm9kdWN0XCIpLnZhbCgpLFxuICAgICAgICAgICAgY2hhbmdlX3R5cGU6ICQoXCIjZmlsdGVyLWNoYW5nZS10eXBlXCIpLnZhbCgpLFxuICAgICAgICAgICAgZGF0ZTogJChcIiNmaWx0ZXItZGF0ZVwiKS52YWwoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gUmVsb2FkIHRhYmxlIGFmdGVyIHJlc2V0XG4gICAgICAgIGNvbnNvbGUubG9nKFwiUmVsb2FkaW5nIHRhYmxlIGFmdGVyIHJlc2V0Li4uXCIpO1xuICAgICAgICB0YWJsZS5hamF4LnJlbG9hZCgpO1xuICAgIH0pO1xufSk7XG5cbndpbmRvdy5zaG93QXVkaXREZXRhaWwgPSBmdW5jdGlvbiAoaWQpIHtcbiAgICBjb25zb2xlLmxvZyhcIlNob3dpbmcgYXVkaXQgZGV0YWlsIGZvciBJRDpcIiwgaWQpO1xuXG4gICAgLy8gUmVzZXQgbW9kYWwgc3RhdGVzIGZpcnN0XG4gICAgJChcIiNtb2RhbC1sb2FkaW5nXCIpLnNob3coKTtcbiAgICAkKFwiI21vZGFsLWVycm9yXCIpLmhpZGUoKTtcbiAgICAkKFwiI21vZGFsLWNvbnRlbnRcIikuaGlkZSgpO1xuXG4gICAgLy8gU2hvdyBtb2RhbFxuICAgICQoXCIjYXVkaXREZXRhaWxNb2RhbFwiKS5tb2RhbChcInNob3dcIik7XG5cbiAgICAkLmFqYXgoe1xuICAgICAgICB1cmw6IGAvd2FyZWhvdXNlL3N0b2NrLWF1ZGl0LyR7aWR9L2RldGFpbGAsXG4gICAgICAgIG1ldGhvZDogXCJHRVRcIixcbiAgICAgICAgc3VjY2VzczogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkRldGFpbCByZXNwb25zZTpcIiwgcmVzcG9uc2UpO1xuICAgICAgICAgICAgJChcIiNtb2RhbC1sb2FkaW5nXCIpLmhpZGUoKTtcblxuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBwb3B1bGF0ZU1vZGFsQ29udGVudChyZXNwb25zZS5kYXRhLCByZXNwb25zZS5zb3VyY2VfZGV0YWlsKTtcbiAgICAgICAgICAgICAgICAkKFwiI21vZGFsLWNvbnRlbnRcIikuc2hvdygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAkKFwiI2Vycm9yLW1lc3NhZ2VcIikudGV4dChyZXNwb25zZS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICAkKFwiI21vZGFsLWVycm9yXCIpLnNob3coKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZXJyb3I6IGZ1bmN0aW9uICh4aHIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJEZXRhaWwgQUpBWCBlcnJvcjpcIiwgeGhyKTtcbiAgICAgICAgICAgICQoXCIjbW9kYWwtbG9hZGluZ1wiKS5oaWRlKCk7XG4gICAgICAgICAgICAkKFwiI2Vycm9yLW1lc3NhZ2VcIikudGV4dChcIkdhZ2FsIG1lbXVhdCBkZXRhaWwgYXVkaXRcIik7XG4gICAgICAgICAgICAkKFwiI21vZGFsLWVycm9yXCIpLnNob3coKTtcbiAgICAgICAgfSxcbiAgICB9KTtcbn07XG5cbmZ1bmN0aW9uIHBvcHVsYXRlTW9kYWxDb250ZW50KGF1ZGl0LCBzb3VyY2VEZXRhaWwpIHtcbiAgICBjb25zb2xlLmxvZyhcIlBvcHVsYXRpbmcgbW9kYWwgY29udGVudDpcIiwgYXVkaXQpO1xuXG4gICAgLy8gUG9wdWxhdGUgYmFzaWMgc3RvY2sgaW5mb3JtYXRpb25cbiAgICAkKFwiI3Byb2R1Y3QtbmFtZVwiKS50ZXh0KGF1ZGl0LnN0b2NrLnByb2R1Y3QubmFtZSk7XG4gICAgJChcIiNkZWFsZXItbmFtZVwiKS50ZXh0KGF1ZGl0LnN0b2NrLmRlYWxlci5uYW1lKTtcbiAgICAkKFwiI3ByZXZpb3VzLXF1YW50aXR5XCIpLnRleHQoYXVkaXQucHJldmlvdXNfcXVhbnRpdHkpO1xuICAgICQoXCIjbmV3LXF1YW50aXR5XCIpLnRleHQoYXVkaXQubmV3X3F1YW50aXR5KTtcbiAgICAkKFwiI3VzZXItbmFtZVwiKS50ZXh0KGF1ZGl0LnVzZXIgPyBhdWRpdC51c2VyLm5hbWUgOiBcIi1cIik7XG4gICAgJChcIiNjcmVhdGVkLWF0XCIpLnRleHQoYXVkaXQuY3JlYXRlZF9hdF9mb3JtYXR0ZWQpO1xuICAgICQoXCIjZGVzY3JpcHRpb25cIikudGV4dChhdWRpdC5kZXNjcmlwdGlvbiB8fCBcIi1cIik7XG5cbiAgICAvLyBTZXQgcXVhbnRpdHkgY2hhbmdlIHdpdGggc3R5bGluZ1xuICAgIGxldCBxdWFudGl0eUNoYW5nZUNsYXNzID0gXCJcIjtcbiAgICBsZXQgcXVhbnRpdHlDaGFuZ2VTaWduID0gXCJcIjtcbiAgICBpZiAoYXVkaXQucXVhbnRpdHlfY2hhbmdlID4gMCkge1xuICAgICAgICBxdWFudGl0eUNoYW5nZUNsYXNzID0gXCJ0ZXh0LXN1Y2Nlc3NcIjtcbiAgICAgICAgcXVhbnRpdHlDaGFuZ2VTaWduID0gXCIrXCI7XG4gICAgfSBlbHNlIGlmIChhdWRpdC5xdWFudGl0eV9jaGFuZ2UgPCAwKSB7XG4gICAgICAgIHF1YW50aXR5Q2hhbmdlQ2xhc3MgPSBcInRleHQtZGFuZ2VyXCI7XG4gICAgICAgIHF1YW50aXR5Q2hhbmdlU2lnbiA9IFwiXCI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVhbnRpdHlDaGFuZ2VDbGFzcyA9IFwidGV4dC1tdXRlZFwiO1xuICAgICAgICBxdWFudGl0eUNoYW5nZVNpZ24gPSBcIlwiO1xuICAgIH1cbiAgICAkKFwiI3F1YW50aXR5LWNoYW5nZVwiKS5odG1sKFxuICAgICAgICBgPHNwYW4gY2xhc3M9XCIke3F1YW50aXR5Q2hhbmdlQ2xhc3N9XCI+JHtxdWFudGl0eUNoYW5nZVNpZ259JHthdWRpdC5xdWFudGl0eV9jaGFuZ2V9PC9zcGFuPmBcbiAgICApO1xuXG4gICAgLy8gU2V0IGNoYW5nZSB0eXBlIHdpdGggc3R5bGluZ1xuICAgIGxldCBjaGFuZ2VUeXBlQ2xhc3MgPSBcIlwiO1xuICAgIHN3aXRjaCAoYXVkaXQuY2hhbmdlX3R5cGUpIHtcbiAgICAgICAgY2FzZSBcImluY3JlYXNlXCI6XG4gICAgICAgICAgICBjaGFuZ2VUeXBlQ2xhc3MgPSBcInRleHQtc3VjY2Vzc1wiO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJkZWNyZWFzZVwiOlxuICAgICAgICAgICAgY2hhbmdlVHlwZUNsYXNzID0gXCJ0ZXh0LWRhbmdlclwiO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJhZGp1c3RtZW50XCI6XG4gICAgICAgICAgICBjaGFuZ2VUeXBlQ2xhc3MgPSBcInRleHQtd2FybmluZ1wiO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjaGFuZ2VUeXBlQ2xhc3MgPSBcInRleHQtbXV0ZWRcIjtcbiAgICB9XG4gICAgJChcIiNjaGFuZ2UtdHlwZVwiKS5odG1sKFxuICAgICAgICBgPHNwYW4gY2xhc3M9XCJmb250LXdlaWdodC1ib2xkICR7Y2hhbmdlVHlwZUNsYXNzfVwiPiR7YXVkaXQuY2hhbmdlX3R5cGVfbGFiZWx9PC9zcGFuPmBcbiAgICApO1xuXG4gICAgLy8gSGFuZGxlIHNvdXJjZSBkZXRhaWxcbiAgICBpZiAoc291cmNlRGV0YWlsKSB7XG4gICAgICAgICQoXCIjc291cmNlLWRldGFpbFwiKS5zaG93KCk7XG5cbiAgICAgICAgaWYgKHNvdXJjZURldGFpbC50eXBlID09PSBcIm11dGF0aW9uXCIpIHtcbiAgICAgICAgICAgIGxldCBtdXRhdGlvbiA9IHNvdXJjZURldGFpbC5kYXRhO1xuICAgICAgICAgICAgJChcIiNzb3VyY2UtdGl0bGVcIikudGV4dChcbiAgICAgICAgICAgICAgICBgTXV0YXNpIFN0b2NrOiAke211dGF0aW9uLm11dGF0aW9uX251bWJlcn1gXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBsZXQgbXV0YXRpb25Db250ZW50ID0gYFxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1tZC02XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGFibGUgY2xhc3M9XCJ0YWJsZSB0YWJsZS1zbVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzdHJvbmc+RGFyaSBEZWFsZXI6PC9zdHJvbmc+PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPiR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbi5mcm9tX2RlYWxlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gbXV0YXRpb24uZnJvbV9kZWFsZXIubmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogXCItXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48c3Ryb25nPktlIERlYWxlcjo8L3N0cm9uZz48L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+JHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0aW9uLnRvX2RlYWxlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gbXV0YXRpb24udG9fZGVhbGVyLm5hbWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IFwiLVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH08L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PHN0cm9uZz5TdGF0dXM6PC9zdHJvbmc+PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPiR7bXV0YXRpb24uc3RhdHVzfTwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGFibGU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLW1kLTZcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0YWJsZSBjbGFzcz1cInRhYmxlIHRhYmxlLXNtXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGQ+PHN0cm9uZz5EaW1pbnRhIG9sZWg6PC9zdHJvbmc+PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPiR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbi5yZXF1ZXN0ZWRfYnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IG11dGF0aW9uLnJlcXVlc3RlZF9ieS5uYW1lXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBcIi1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3RyPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzdHJvbmc+RGlzZXR1anVpIG9sZWg6PC9zdHJvbmc+PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHRkPiR7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGlvbi5hcHByb3ZlZF9ieVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gbXV0YXRpb24uYXBwcm92ZWRfYnkubmFtZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogXCItXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfTwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD48c3Ryb25nPlRhbmdnYWwgRGlzZXR1anVpOjwvc3Ryb25nPjwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0ZD4ke1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRpb24uYXBwcm92ZWRfYXRfZm9ybWF0dGVkIHx8IFwiLVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH08L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3RhYmxlPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIGA7XG4gICAgICAgICAgICAkKFwiI3NvdXJjZS1jb250ZW50XCIpLmh0bWwobXV0YXRpb25Db250ZW50KTtcbiAgICAgICAgfSBlbHNlIGlmIChzb3VyY2VEZXRhaWwudHlwZSA9PT0gXCJvcG5hbWVcIikge1xuICAgICAgICAgICAgbGV0IG9wbmFtZSA9IHNvdXJjZURldGFpbC5kYXRhO1xuICAgICAgICAgICAgJChcIiNzb3VyY2UtdGl0bGVcIikudGV4dChcIk9wbmFtZVwiKTtcblxuICAgICAgICAgICAgbGV0IG9wbmFtZUNvbnRlbnQgPSBgXG4gICAgICAgICAgICAgICAgPHRhYmxlIGNsYXNzPVwidGFibGUgdGFibGUtc21cIj5cbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzdHJvbmc+RGVhbGVyOjwvc3Ryb25nPjwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+JHtvcG5hbWUuZGVhbGVyID8gb3BuYW1lLmRlYWxlci5uYW1lIDogXCItXCJ9PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzdHJvbmc+VXNlcjo8L3N0cm9uZz48L3RkPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPiR7b3BuYW1lLnVzZXIgPyBvcG5hbWUudXNlci5uYW1lIDogXCItXCJ9PC90ZD5cbiAgICAgICAgICAgICAgICAgICAgPC90cj5cbiAgICAgICAgICAgICAgICAgICAgPHRyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkPjxzdHJvbmc+U3RhdHVzOjwvc3Ryb25nPjwvdGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQ+JHtvcG5hbWUuc3RhdHVzIHx8IFwiLVwifTwvdGQ+XG4gICAgICAgICAgICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgICAgICAgPC90YWJsZT5cbiAgICAgICAgICAgIGA7XG4gICAgICAgICAgICAkKFwiI3NvdXJjZS1jb250ZW50XCIpLmh0bWwob3BuYW1lQ29udGVudCk7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICAkKFwiI3NvdXJjZS1kZXRhaWxcIikuaGlkZSgpO1xuICAgIH1cbn1cbiJdLCJtYXBwaW5ncyI6IkFBQUFBLE9BQU8sQ0FBQ0MsR0FBUixDQUFZLHVCQUFaLEUsQ0FFQTs7QUFDQSxTQUFTQyxVQUFULENBQW9CQyxVQUFwQixFQUFnQztFQUM1QixJQUFJLENBQUNBLFVBQUwsRUFBaUIsT0FBTyxHQUFQO0VBRWpCLElBQU1DLElBQUksR0FBRyxJQUFJQyxJQUFKLENBQVNGLFVBQVQsQ0FBYjtFQUNBLElBQU1HLE1BQU0sR0FBRyxDQUNYLEtBRFcsRUFFWCxLQUZXLEVBR1gsS0FIVyxFQUlYLEtBSlcsRUFLWCxLQUxXLEVBTVgsS0FOVyxFQU9YLEtBUFcsRUFRWCxLQVJXLEVBU1gsS0FUVyxFQVVYLEtBVlcsRUFXWCxLQVhXLEVBWVgsS0FaVyxDQUFmO0VBZUEsSUFBTUMsR0FBRyxHQUFHSCxJQUFJLENBQUNJLE9BQUwsR0FBZUMsUUFBZixHQUEwQkMsUUFBMUIsQ0FBbUMsQ0FBbkMsRUFBc0MsR0FBdEMsQ0FBWjtFQUNBLElBQU1DLEtBQUssR0FBR0wsTUFBTSxDQUFDRixJQUFJLENBQUNRLFFBQUwsRUFBRCxDQUFwQjtFQUNBLElBQU1DLElBQUksR0FBR1QsSUFBSSxDQUFDVSxXQUFMLEVBQWI7RUFDQSxJQUFNQyxLQUFLLEdBQUdYLElBQUksQ0FBQ1ksUUFBTCxHQUFnQlAsUUFBaEIsR0FBMkJDLFFBQTNCLENBQW9DLENBQXBDLEVBQXVDLEdBQXZDLENBQWQ7RUFDQSxJQUFNTyxPQUFPLEdBQUdiLElBQUksQ0FBQ2MsVUFBTCxHQUFrQlQsUUFBbEIsR0FBNkJDLFFBQTdCLENBQXNDLENBQXRDLEVBQXlDLEdBQXpDLENBQWhCO0VBRUEsaUJBQVVILEdBQVYsY0FBaUJJLEtBQWpCLGNBQTBCRSxJQUExQixlQUFtQ0UsS0FBbkMsY0FBNENFLE9BQTVD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\n//# sourceURL=webpack-internal:///./resources/js/warehouse_management/stock_audit/index.js\n"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ +/******/ // startup +/******/ // Load entry module and return exports +/******/ // This entry module can't be inlined because the eval-source-map devtool is used. +/******/ var __webpack_exports__ = {}; +/******/ __webpack_modules__["./resources/js/warehouse_management/stock_audit/index.js"](); +/******/ +/******/ })() +; \ No newline at end of file diff --git a/public/js/warehouse_management/stock_audit/index.js.map b/public/js/warehouse_management/stock_audit/index.js.map new file mode 100644 index 0000000..02e8852 --- /dev/null +++ b/public/js/warehouse_management/stock_audit/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"/js/warehouse_management/stock_audit/index.js","mappings":"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","sources":["webpack:///./resources/js/warehouse_management/stock_audit/index.js"],"sourcesContent":["console.log(\"Stock audit JS loaded\");\n\n$(document).ready(function () {\n console.log(\"Initializing stock audit table...\");\n\n // Initialize Select2 without any event handlers\n $(\".select2\").select2({\n placeholder: \"Pilih...\",\n allowClear: true,\n width: \"100%\",\n });\n\n // Initialize Datepicker\n $(\".datepicker\").datepicker({\n format: \"yyyy-mm-dd\",\n autoclose: true,\n todayHighlight: true,\n orientation: \"bottom auto\",\n language: \"id\",\n clearBtn: true,\n container: \"body\",\n });\n\n const $table = $(\"#stock-audit-table\");\n const indexRoute = $table.data(\"route\");\n\n console.log(\"Table route:\", indexRoute);\n\n let table = $table.DataTable({\n processing: true,\n serverSide: true,\n language: {\n processing:\n '
Memproses...
',\n loadingRecords: \"Memuat data...\",\n zeroRecords: \"Tidak ada data yang ditemukan\",\n emptyTable: \"Tidak ada data tersedia\",\n },\n ajax: {\n url: indexRoute,\n data: function (d) {\n d.dealer = $(\"#filter-dealer\").val();\n d.product = $(\"#filter-product\").val();\n d.change_type = $(\"#filter-change-type\").val();\n d.date = $(\"#filter-date\").val();\n console.log(\"Ajax data with ordering:\", d);\n console.log(\"Order info:\", d.order);\n console.log(\"Columns info:\", d.columns);\n },\n error: function (xhr, error, thrown) {\n console.error(\"Ajax error:\", error);\n console.error(\"Response:\", xhr.responseText);\n },\n },\n columns: [\n {\n data: \"DT_RowIndex\",\n name: \"DT_RowIndex\",\n orderable: false,\n searchable: false,\n width: \"5%\",\n },\n {\n data: \"product_name\",\n name: \"product_name\",\n orderable: true,\n },\n {\n data: \"dealer_name\",\n name: \"dealer_name\",\n orderable: true,\n },\n {\n data: \"change_type\",\n name: \"change_type\",\n orderable: true,\n },\n {\n data: \"quantity_change\",\n name: \"quantity_change\",\n className: \"text-center\",\n orderable: true,\n },\n {\n data: \"stock_before_after\",\n name: \"stock_before_after\",\n className: \"text-center\",\n orderable: true,\n },\n {\n data: \"source_info\",\n name: \"source_info\",\n orderable: true,\n },\n {\n data: \"user_name\",\n name: \"user_name\",\n orderable: true,\n },\n {\n data: \"created_at\",\n name: \"created_at\",\n orderable: true,\n },\n {\n data: \"action\",\n name: \"action\",\n orderable: false,\n searchable: false,\n width: \"10%\",\n },\n ],\n order: [[8, \"desc\"]], // Order by created_at desc (column index 8)\n pageLength: 25,\n responsive: true,\n ordering: true, // Enable column ordering\n orderMulti: false, // Single column ordering only\n });\n\n console.log(\"Table initialized:\", table);\n\n // Add loading indicator for ordering\n table.on(\"processing.dt\", function (e, settings, processing) {\n if (processing) {\n console.log(\"DataTable processing started (ordering/filtering)\");\n } else {\n console.log(\"DataTable processing finished\");\n }\n });\n\n // Debug order events\n table.on(\"order.dt\", function () {\n console.log(\"Order changed:\", table.order());\n });\n\n // Manual modal close handlers\n $(document).on(\n \"click\",\n \"#modal-close-btn, #modal-close-footer-btn\",\n function () {\n console.log(\"Manual close button clicked\");\n $(\"#auditDetailModal\").modal(\"hide\");\n }\n );\n\n // Modal backdrop click handler\n $(document).on(\"click\", \"#auditDetailModal\", function (e) {\n if (e.target === this) {\n console.log(\"Modal backdrop clicked\");\n $(\"#auditDetailModal\").modal(\"hide\");\n }\n });\n\n // ESC key handler\n $(document).on(\"keydown\", function (e) {\n if (e.keyCode === 27 && $(\"#auditDetailModal\").hasClass(\"show\")) {\n console.log(\"ESC key pressed\");\n $(\"#auditDetailModal\").modal(\"hide\");\n }\n });\n\n // Modal hidden event handler\n $(\"#auditDetailModal\").on(\"hidden.bs.modal\", function () {\n console.log(\"Modal hidden\");\n // Reset modal content\n $(\"#modal-loading\").show();\n $(\"#modal-error\").hide();\n $(\"#modal-content\").hide();\n });\n\n // Apply filters button - only way to trigger table reload\n $(\"#apply-filters\").click(function () {\n console.log(\"Apply filters clicked, reloading table...\");\n console.log(\"Current filter values:\", {\n dealer: $(\"#filter-dealer\").val(),\n product: $(\"#filter-product\").val(),\n change_type: $(\"#filter-change-type\").val(),\n date: $(\"#filter-date\").val(),\n });\n table.ajax.reload();\n });\n\n // Allow Enter key to apply filters on datepicker\n $(\"#filter-date\").keypress(function (e) {\n if (e.which == 13) {\n // Enter key\n console.log(\"Enter pressed on date filter, applying filters...\");\n table.ajax.reload();\n }\n });\n\n // Reset filters\n $(\"#reset-filters\").click(function () {\n console.log(\"Resetting filters...\");\n\n // Reset select2 elements properly\n $(\"#filter-dealer\").val(null).trigger(\"change.select2\");\n $(\"#filter-product\").val(null).trigger(\"change.select2\");\n $(\"#filter-change-type\").val(null).trigger(\"change.select2\");\n\n // Reset datepicker properly\n $(\"#filter-date\").val(\"\").datepicker(\"update\");\n\n console.log(\"Filters reset, values after reset:\", {\n dealer: $(\"#filter-dealer\").val(),\n product: $(\"#filter-product\").val(),\n change_type: $(\"#filter-change-type\").val(),\n date: $(\"#filter-date\").val(),\n });\n\n // Reload table after reset\n console.log(\"Reloading table after reset...\");\n table.ajax.reload();\n });\n});\n\nwindow.showAuditDetail = function (id) {\n console.log(\"Showing audit detail for ID:\", id);\n\n // Reset modal states first\n $(\"#modal-loading\").show();\n $(\"#modal-error\").hide();\n $(\"#modal-content\").hide();\n\n // Show modal\n $(\"#auditDetailModal\").modal(\"show\");\n\n $.ajax({\n url: `/warehouse/stock-audit/${id}/detail`,\n method: \"GET\",\n success: function (response) {\n console.log(\"Detail response:\", response);\n $(\"#modal-loading\").hide();\n\n if (response.success) {\n populateModalContent(response.data, response.source_detail);\n $(\"#modal-content\").show();\n } else {\n $(\"#error-message\").text(response.message);\n $(\"#modal-error\").show();\n }\n },\n error: function (xhr) {\n console.error(\"Detail AJAX error:\", xhr);\n $(\"#modal-loading\").hide();\n $(\"#error-message\").text(\"Gagal memuat detail audit\");\n $(\"#modal-error\").show();\n },\n });\n};\n\nfunction populateModalContent(audit, sourceDetail) {\n console.log(\"Populating modal content:\", audit);\n\n // Populate basic stock information\n $(\"#product-name\").text(audit.stock.product.name);\n $(\"#dealer-name\").text(audit.stock.dealer.name);\n $(\"#previous-quantity\").text(audit.previous_quantity);\n $(\"#new-quantity\").text(audit.new_quantity);\n $(\"#user-name\").text(audit.user ? audit.user.name : \"-\");\n $(\"#created-at\").text(audit.created_at_formatted);\n $(\"#description\").text(audit.description || \"-\");\n\n // Set quantity change with styling\n let quantityChangeClass = \"\";\n let quantityChangeSign = \"\";\n if (audit.quantity_change > 0) {\n quantityChangeClass = \"text-success\";\n quantityChangeSign = \"+\";\n } else if (audit.quantity_change < 0) {\n quantityChangeClass = \"text-danger\";\n quantityChangeSign = \"\";\n } else {\n quantityChangeClass = \"text-muted\";\n quantityChangeSign = \"\";\n }\n $(\"#quantity-change\").html(\n `${quantityChangeSign}${audit.quantity_change}`\n );\n\n // Set change type with styling\n let changeTypeClass = \"\";\n switch (audit.change_type) {\n case \"increase\":\n changeTypeClass = \"text-success\";\n break;\n case \"decrease\":\n changeTypeClass = \"text-danger\";\n break;\n case \"adjustment\":\n changeTypeClass = \"text-warning\";\n break;\n default:\n changeTypeClass = \"text-muted\";\n }\n $(\"#change-type\").html(\n `${audit.change_type_label}`\n );\n\n // Handle source detail\n if (sourceDetail) {\n $(\"#source-detail\").show();\n\n if (sourceDetail.type === \"mutation\") {\n let mutation = sourceDetail.data;\n $(\"#source-title\").text(\n `Mutasi Stock: ${mutation.mutation_number}`\n );\n\n let mutationContent = `\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
Dari Dealer:${\n mutation.from_dealer\n ? mutation.from_dealer.name\n : \"-\"\n }
Ke Dealer:${\n mutation.to_dealer\n ? mutation.to_dealer.name\n : \"-\"\n }
Status:${mutation.status}
\n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
Diminta oleh:${\n mutation.requested_by\n ? mutation.requested_by.name\n : \"-\"\n }
Disetujui oleh:${\n mutation.approved_by\n ? mutation.approved_by.name\n : \"-\"\n }
Tanggal Disetujui:${mutation.approved_at || \"-\"}
\n
\n
\n `;\n $(\"#source-content\").html(mutationContent);\n } else if (sourceDetail.type === \"opname\") {\n let opname = sourceDetail.data;\n $(\"#source-title\").text(\"Opname\");\n\n let opnameContent = `\n \n \n \n \n \n \n \n \n \n \n \n \n \n
Dealer:${opname.dealer ? opname.dealer.name : \"-\"}
User:${opname.user ? opname.user.name : \"-\"}
Status:${opname.status || \"-\"}
\n `;\n $(\"#source-content\").html(opnameContent);\n }\n } else {\n $(\"#source-detail\").hide();\n }\n}\n"],"names":["console","log","$","document","ready","select2","placeholder","allowClear","width","datepicker","format","autoclose","todayHighlight","orientation","language","clearBtn","container","$table","indexRoute","data","table","DataTable","processing","serverSide","loadingRecords","zeroRecords","emptyTable","ajax","url","d","dealer","val","product","change_type","date","order","columns","error","xhr","thrown","responseText","name","orderable","searchable","className","pageLength","responsive","ordering","orderMulti","on","e","settings","modal","target","this","keyCode","hasClass","show","hide","click","reload","keypress","which","trigger","window","showAuditDetail","id","method","success","response","audit","sourceDetail","text","stock","previous_quantity","new_quantity","user","created_at_formatted","description","quantityChangeClass","quantityChangeSign","quantity_change","html","changeTypeClass","change_type_label","type","mutation","mutation_number","mutationContent","from_dealer","to_dealer","status","requested_by","approved_by","approved_at","opname","opnameContent","populateModalContent","source_detail","message"],"sourceRoot":""} \ No newline at end of file diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 7aadca0..975b60f 100755 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -8,6 +8,7 @@ "/js/warehouse_management/opnames/detail.js": "/js/warehouse_management/opnames/detail.js", "/js/warehouse_management/mutations/index.js": "/js/warehouse_management/mutations/index.js", "/js/warehouse_management/mutations/create.js": "/js/warehouse_management/mutations/create.js", + "/js/warehouse_management/stock_audit/index.js": "/js/warehouse_management/stock_audit/index.js", "/css/app.css": "/css/app.css", "/js/vendor/jquery.dataTables.min.js": "/js/vendor/jquery.dataTables.min.js", "/js/vendor/dataTables.bootstrap4.min.js": "/js/vendor/dataTables.bootstrap4.min.js", diff --git a/resources/js/warehouse_management/stock_audit/index.js b/resources/js/warehouse_management/stock_audit/index.js new file mode 100644 index 0000000..e78bce7 --- /dev/null +++ b/resources/js/warehouse_management/stock_audit/index.js @@ -0,0 +1,419 @@ +console.log("Stock audit JS loaded"); + +// Helper function to format date +function formatDate(dateString) { + if (!dateString) return "-"; + + const date = new Date(dateString); + const months = [ + "Jan", + "Feb", + "Mar", + "Apr", + "Mei", + "Jun", + "Jul", + "Agu", + "Sep", + "Okt", + "Nov", + "Des", + ]; + + const day = date.getDate().toString().padStart(2, "0"); + const month = months[date.getMonth()]; + const year = date.getFullYear(); + const hours = date.getHours().toString().padStart(2, "0"); + const minutes = date.getMinutes().toString().padStart(2, "0"); + + return `${day} ${month} ${year}, ${hours}:${minutes}`; +} + +$(document).ready(function () { + console.log("Initializing stock audit table..."); + + // Initialize Select2 without any event handlers + $(".select2").select2({ + placeholder: "Pilih...", + allowClear: true, + width: "100%", + }); + + // Initialize Datepicker + $(".datepicker").datepicker({ + format: "yyyy-mm-dd", + autoclose: true, + todayHighlight: true, + orientation: "bottom auto", + language: "id", + clearBtn: true, + container: "body", + }); + + const $table = $("#stock-audit-table"); + const indexRoute = $table.data("route"); + + console.log("Table route:", indexRoute); + + let table = $table.DataTable({ + processing: true, + serverSide: true, + language: { + processing: + '
Memproses...
', + loadingRecords: "Memuat data...", + zeroRecords: "Tidak ada data yang ditemukan", + emptyTable: "Tidak ada data tersedia", + }, + ajax: { + url: indexRoute, + data: function (d) { + d.dealer = $("#filter-dealer").val(); + d.product = $("#filter-product").val(); + d.change_type = $("#filter-change-type").val(); + d.date = $("#filter-date").val(); + console.log("Ajax data with ordering:", d); + console.log("Order info:", d.order); + console.log("Columns info:", d.columns); + }, + error: function (xhr, error, thrown) { + console.error("Ajax error:", error); + console.error("Response:", xhr.responseText); + }, + }, + columns: [ + { + data: "DT_RowIndex", + name: "DT_RowIndex", + orderable: false, + searchable: false, + width: "5%", + }, + { + data: "product_name", + name: "product_name", + orderable: true, + }, + { + data: "dealer_name", + name: "dealer_name", + orderable: true, + }, + { + data: "change_type", + name: "change_type", + orderable: true, + }, + { + data: "quantity_change", + name: "quantity_change", + className: "text-center", + orderable: true, + }, + { + data: "stock_before_after", + name: "stock_before_after", + className: "text-center", + orderable: true, + }, + { + data: "source_info", + name: "source_info", + orderable: true, + }, + { + data: "user_name", + name: "user_name", + orderable: true, + }, + { + data: "created_at", + name: "created_at", + orderable: true, + }, + { + data: "action", + name: "action", + orderable: false, + searchable: false, + width: "10%", + }, + ], + order: [[8, "desc"]], // Order by created_at desc (column index 8) + pageLength: 25, + responsive: true, + ordering: true, // Enable column ordering + orderMulti: false, // Single column ordering only + }); + + console.log("Table initialized:", table); + + // Add loading indicator for ordering + table.on("processing.dt", function (e, settings, processing) { + if (processing) { + console.log("DataTable processing started (ordering/filtering)"); + } else { + console.log("DataTable processing finished"); + } + }); + + // Debug order events + table.on("order.dt", function () { + console.log("Order changed:", table.order()); + }); + + // Manual modal close handlers + $(document).on( + "click", + "#modal-close-btn, #modal-close-footer-btn", + function () { + console.log("Manual close button clicked"); + $("#auditDetailModal").modal("hide"); + } + ); + + // Modal backdrop click handler + $(document).on("click", "#auditDetailModal", function (e) { + if (e.target === this) { + console.log("Modal backdrop clicked"); + $("#auditDetailModal").modal("hide"); + } + }); + + // ESC key handler + $(document).on("keydown", function (e) { + if (e.keyCode === 27 && $("#auditDetailModal").hasClass("show")) { + console.log("ESC key pressed"); + $("#auditDetailModal").modal("hide"); + } + }); + + // Modal hidden event handler + $("#auditDetailModal").on("hidden.bs.modal", function () { + console.log("Modal hidden"); + // Reset modal content + $("#modal-loading").show(); + $("#modal-error").hide(); + $("#modal-content").hide(); + }); + + // Apply filters button - only way to trigger table reload + $("#apply-filters").click(function () { + console.log("Apply filters clicked, reloading table..."); + console.log("Current filter values:", { + dealer: $("#filter-dealer").val(), + product: $("#filter-product").val(), + change_type: $("#filter-change-type").val(), + date: $("#filter-date").val(), + }); + table.ajax.reload(); + }); + + // Allow Enter key to apply filters on datepicker + $("#filter-date").keypress(function (e) { + if (e.which == 13) { + // Enter key + console.log("Enter pressed on date filter, applying filters..."); + table.ajax.reload(); + } + }); + + // Reset filters + $("#reset-filters").click(function () { + console.log("Resetting filters..."); + + // Reset select2 elements properly + $("#filter-dealer").val(null).trigger("change.select2"); + $("#filter-product").val(null).trigger("change.select2"); + $("#filter-change-type").val(null).trigger("change.select2"); + + // Reset datepicker properly + $("#filter-date").val("").datepicker("update"); + + console.log("Filters reset, values after reset:", { + dealer: $("#filter-dealer").val(), + product: $("#filter-product").val(), + change_type: $("#filter-change-type").val(), + date: $("#filter-date").val(), + }); + + // Reload table after reset + console.log("Reloading table after reset..."); + table.ajax.reload(); + }); +}); + +window.showAuditDetail = function (id) { + console.log("Showing audit detail for ID:", id); + + // Reset modal states first + $("#modal-loading").show(); + $("#modal-error").hide(); + $("#modal-content").hide(); + + // Show modal + $("#auditDetailModal").modal("show"); + + $.ajax({ + url: `/warehouse/stock-audit/${id}/detail`, + method: "GET", + success: function (response) { + console.log("Detail response:", response); + $("#modal-loading").hide(); + + if (response.success) { + populateModalContent(response.data, response.source_detail); + $("#modal-content").show(); + } else { + $("#error-message").text(response.message); + $("#modal-error").show(); + } + }, + error: function (xhr) { + console.error("Detail AJAX error:", xhr); + $("#modal-loading").hide(); + $("#error-message").text("Gagal memuat detail audit"); + $("#modal-error").show(); + }, + }); +}; + +function populateModalContent(audit, sourceDetail) { + console.log("Populating modal content:", audit); + + // Populate basic stock information + $("#product-name").text(audit.stock.product.name); + $("#dealer-name").text(audit.stock.dealer.name); + $("#previous-quantity").text(audit.previous_quantity); + $("#new-quantity").text(audit.new_quantity); + $("#user-name").text(audit.user ? audit.user.name : "-"); + $("#created-at").text(audit.created_at_formatted); + $("#description").text(audit.description || "-"); + + // Set quantity change with styling + let quantityChangeClass = ""; + let quantityChangeSign = ""; + if (audit.quantity_change > 0) { + quantityChangeClass = "text-success"; + quantityChangeSign = "+"; + } else if (audit.quantity_change < 0) { + quantityChangeClass = "text-danger"; + quantityChangeSign = ""; + } else { + quantityChangeClass = "text-muted"; + quantityChangeSign = ""; + } + $("#quantity-change").html( + `${quantityChangeSign}${audit.quantity_change}` + ); + + // Set change type with styling + let changeTypeClass = ""; + switch (audit.change_type) { + case "increase": + changeTypeClass = "text-success"; + break; + case "decrease": + changeTypeClass = "text-danger"; + break; + case "adjustment": + changeTypeClass = "text-warning"; + break; + default: + changeTypeClass = "text-muted"; + } + $("#change-type").html( + `${audit.change_type_label}` + ); + + // Handle source detail + if (sourceDetail) { + $("#source-detail").show(); + + if (sourceDetail.type === "mutation") { + let mutation = sourceDetail.data; + $("#source-title").text( + `Mutasi Stock: ${mutation.mutation_number}` + ); + + let mutationContent = ` +
+
+ + + + + + + + + + + + + +
Dari Dealer:${ + mutation.from_dealer + ? mutation.from_dealer.name + : "-" + }
Ke Dealer:${ + mutation.to_dealer + ? mutation.to_dealer.name + : "-" + }
Status:${mutation.status}
+
+
+ + + + + + + + + + + + + +
Diminta oleh:${ + mutation.requested_by + ? mutation.requested_by.name + : "-" + }
Disetujui oleh:${ + mutation.approved_by + ? mutation.approved_by.name + : "-" + }
Tanggal Disetujui:${ + mutation.approved_at_formatted || "-" + }
+
+
+ `; + $("#source-content").html(mutationContent); + } else if (sourceDetail.type === "opname") { + let opname = sourceDetail.data; + $("#source-title").text("Opname"); + + let opnameContent = ` + + + + + + + + + + + + + +
Dealer:${opname.dealer ? opname.dealer.name : "-"}
User:${opname.user ? opname.user.name : "-"}
Status:${opname.status || "-"}
+ `; + $("#source-content").html(opnameContent); + } + } else { + $("#source-detail").hide(); + } +} diff --git a/resources/views/layouts/partials/sidebarMenu.blade.php b/resources/views/layouts/partials/sidebarMenu.blade.php index 43c303d..4cbf123 100755 --- a/resources/views/layouts/partials/sidebarMenu.blade.php +++ b/resources/views/layouts/partials/sidebarMenu.blade.php @@ -146,6 +146,15 @@ @endcan + @can('view', $menus['stock-audit.index']) +
  • + + + Histori Stock + +
  • + @endcan + {{-- Section Header --}}
    diff --git a/resources/views/warehouse_management/stock_audit/index.blade.php b/resources/views/warehouse_management/stock_audit/index.blade.php new file mode 100644 index 0000000..e4b5b92 --- /dev/null +++ b/resources/views/warehouse_management/stock_audit/index.blade.php @@ -0,0 +1,220 @@ +@extends('layouts.backapp') + +@section('styles') + +@endsection + +@section('content') +
    +
    +
    + +

    + Histori Stock +

    +
    +
    + +
    + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    + + +
    +
    +
    + +
    + + + + + + + + + + + + + + + +
    NoProdukDealerJenis PerubahanPerubahan QtyStock (Sebelum → Sesudah)SumberUserTanggalAksi
    +
    +
    +
    + + + + +@endsection + +@section('javascripts') + +@endsection + + \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index ad24141..749e4f7 100755 --- a/routes/web.php +++ b/routes/web.php @@ -12,6 +12,7 @@ use App\Http\Controllers\WarehouseManagement\ProductCategoriesController; use App\Http\Controllers\WarehouseManagement\ProductsController; use App\Http\Controllers\WorkController; use App\Http\Controllers\WarehouseManagement\MutationsController; +use App\Http\Controllers\WarehouseManagement\StockAuditController; use App\Models\Menu; use App\Models\Privilege; use App\Models\Role; @@ -257,6 +258,11 @@ Route::group(['middleware' => 'auth'], function() { Route::post('{mutation}/complete', 'complete')->name('complete'); Route::post('{mutation}/cancel', 'cancel')->name('cancel'); }); + + Route::prefix('stock-audit')->name('stock-audit.')->controller(StockAuditController::class)->group(function () { + Route::get('/', 'index')->name('index'); + Route::get('{stockLog}/detail', 'getDetail')->name('detail'); + }); }); }); diff --git a/webpack.mix.js b/webpack.mix.js index 357e0cd..2576d42 100755 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -42,6 +42,10 @@ mix.js("resources/js/app.js", "public/js") "resources/js/warehouse_management/mutations/create.js", "public/js/warehouse_management/mutations" ) + .js( + "resources/js/warehouse_management/stock_audit/index.js", + "public/js/warehouse_management/stock_audit" + ) // Copy vendor libraries from node_modules .copy( "node_modules/datatables.net/js/jquery.dataTables.min.js",