diff --git a/app/Http/Controllers/WarehouseManagement/OpnamesController.php b/app/Http/Controllers/WarehouseManagement/OpnamesController.php
index 688bc09..d5d23fe 100644
--- a/app/Http/Controllers/WarehouseManagement/OpnamesController.php
+++ b/app/Http/Controllers/WarehouseManagement/OpnamesController.php
@@ -3,8 +3,11 @@
namespace App\Http\Controllers\WarehouseManagement;
use App\Http\Controllers\Controller;
+use App\Models\Dealer;
use App\Models\Menu;
use App\Models\Opname;
+use App\Models\OpnameDetail;
+use App\Models\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
@@ -41,12 +44,52 @@ class OpnamesController extends Controller
}
public function create(){
- return view('warehouse_management.opnames.create');
+ try{
+ $dealers = Dealer::all();
+ $products = Product::all();
+ return view('warehouse_management.opnames.create', compact('dealers','products'));
+ }catch(\Exception $ex){
+ Log::error($ex->getMessage());
+ }
}
public function store(Request $request){
try{
-
+ $request->validate([
+ 'dealer' => 'required|exists:dealers,id',
+ 'product' => 'required|array',
+ 'product.*' => 'nullable|exists:products,id',
+ 'system_quantity' => 'required|array',
+ 'physical_quantity' => 'required|array',
+ ]);
+
+ // 1. Create Opname master record
+ $opname = Opname::create([
+ 'dealer_id' => $request->dealer,
+ 'opname_date' => now(), // or $request->opname_date if you provide it
+ 'user_id' => auth()->id(), // assuming the user is logged in
+ 'note' => null, // or $request->note if needed
+ ]);
+
+ // 2. Loop over products to create OpnameDetails
+ foreach ($request->product as $index => $productId) {
+ if (!$productId) continue; // Skip empty rows
+
+ $system = $request->system_quantity[$index] ?? 0;
+ $physical = $request->physical_quantity[$index] ?? 0;
+
+ OpnameDetail::create([
+ 'opname_id' => $opname->id,
+ 'product_id' => $productId,
+ 'system_stock' => $system,
+ 'physical_stock' => $physical,
+ 'difference' => $physical - $system,
+ 'note' => null, // or include from input
+ ]);
+ }
+
+ return redirect()->route('opnames.index')
+ ->with('success', 'Opname berhasil disimpan.');
}catch(\Exception $ex){
Log::error($ex->getMessage());
}
diff --git a/app/Http/Controllers/WarehouseManagement/ProductsController.php b/app/Http/Controllers/WarehouseManagement/ProductsController.php
index f3f129c..62c7d5f 100644
--- a/app/Http/Controllers/WarehouseManagement/ProductsController.php
+++ b/app/Http/Controllers/WarehouseManagement/ProductsController.php
@@ -25,14 +25,14 @@ class ProductsController extends Controller
{
$menu = Menu::where('link','products.index')->first();
if($request->ajax()){
- $data = Product::with(['category','dealers']);
+ $data = Product::with(['category','opnameDetails']);
return DataTables::of($data)
->addIndexColumn()
->addColumn('category_name', function ($row) {
return $row->category ? $row->category->name : '-';
})
->addColumn('total_stock', function ($row){
- return 0;
+ return $row->opnameDetails->sum('system_stock');
})
->addColumn('action', function ($row) use ($menu) {
$btn = '
';
@@ -46,8 +46,11 @@ class ProductsController extends Controller
data-url="' . route('products.toggleActive', $row->id) . '" data-active="'.$row->active.'" style="margin-right: 8px;">'
. ($row->active ? 'Nonaktifkan' : 'Aktifkan') . '';
- $btn .= '';
-
+ $btn .= '';
+
$btn .= '
';
return $btn;
@@ -104,6 +107,7 @@ class ProductsController extends Controller
return redirect()->route('products.index')->with('success', 'Produk berhasil ditambahkan.');
}catch(\Exception $ex){
+ Log::error($ex->getMessage());
throw $ex;
}
}
@@ -174,34 +178,12 @@ class ProductsController extends Controller
*/
public function destroy(Product $product)
{
- // Ambil stok pivot sebelum hapus
- $dealerStocks = $product->dealers()->pluck('quantity', 'dealer_id')->toArray();
-
- // Buat mutasi stok keluar (out) untuk semua stok yang dihapus
- foreach ($dealerStocks as $dealerId => $qty) {
- if ($qty > 0) {
- StockMutation::create([
- 'product_id' => $product->id,
- 'dealer_id' => $dealerId,
- 'mutation_type' => 'out',
- 'quantity' => $qty,
- 'description' => 'Stock removed due to product deletion',
- 'user_id' => auth()->id(),
- ]);
- }
- }
-
- // Hapus pivot stok dealer
- $product->dealers()->detach();
-
- // Hapus produk
$product->delete();
return redirect()->route('products.index')->with('success', 'Produk berhasil dihapus.');
}
public function toggleActive(Request $request, Product $product)
{
- // You can add authorization here
$product->active = !$product->active;
$product->save();
@@ -211,4 +193,33 @@ class ProductsController extends Controller
'message' => 'Status produk berhasil diperbarui.'
]);
}
+
+ public function all_products(){
+ try{
+ $products = Product::select('id','name')->get();
+ return response()->json($products);
+ }catch(\Exception $ex){
+ Log::error($ex->getMessage());
+ }
+ }
+
+ public function dealers_stock(Request $request){
+ $productId = $request->get('product_id');
+
+ $product = Product::with(['opnameDetails.opname.dealer'])->findOrFail($productId);
+
+ $opnameDetails = $product->opnameDetails;
+
+ $data = $opnameDetails->map(function ($detail) {
+ return [
+ 'dealer_name' => $detail->opname->dealer->name ?? '-',
+ 'system_stock' => $detail->system_stock,
+ 'physical_stock' => $detail->physical_stock,
+ 'difference' => $detail->physical_stock - $detail->system_stock,
+ 'opname_date' => optional($detail->opname)->created_at->format('d M Y')
+ ];
+ });
+
+ return DataTables::of($data)->make(true);
+ }
}
diff --git a/public/js/warehouse_management/opnames/create.js b/public/js/warehouse_management/opnames/create.js
new file mode 100644
index 0000000..86dfcb8
--- /dev/null
+++ b/public/js/warehouse_management/opnames/create.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/opnames/create.js":
+/*!*************************************************************!*\
+ !*** ./resources/js/warehouse_management/opnames/create.js ***!
+ \*************************************************************/
+/***/ (() => {
+
+eval("var productUrl = $(\"#product-container\").data(\"url\");\n\nfunction createProductSelectOptions(callback) {\n $.ajax({\n url: productUrl,\n method: \"GET\",\n success: function success(data) {\n var options = '';\n data.forEach(function (product) {\n options += \"\");\n });\n callback(options);\n },\n error: function error() {\n alert(\"Gagal memuat produk.\");\n }\n });\n}\n\n$(document).ready(function () {\n // Initial load only for the first row\n createProductSelectOptions(function (options) {\n $(\".product-select\").first().html(options);\n }); // When adding a new row\n\n $(document).on(\"click\", \".btn-add-row\", function () {\n var row = \"\\n \\n \";\n var $newRow = $(row);\n $(\"#product-container\").append($newRow); // Load options only for the new select\n\n createProductSelectOptions(function (options) {\n $newRow.find(\".product-select\").html(options);\n });\n }); // Remove row\n\n $(document).on(\"click\", \".btn-remove-row\", function () {\n $(this).closest(\".product-row\").remove();\n });\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvb3BuYW1lcy9jcmVhdGUuanMiLCJuYW1lcyI6WyJwcm9kdWN0VXJsIiwiJCIsImRhdGEiLCJjcmVhdGVQcm9kdWN0U2VsZWN0T3B0aW9ucyIsImNhbGxiYWNrIiwiYWpheCIsInVybCIsIm1ldGhvZCIsInN1Y2Nlc3MiLCJvcHRpb25zIiwiZm9yRWFjaCIsInByb2R1Y3QiLCJpZCIsIm5hbWUiLCJlcnJvciIsImFsZXJ0IiwiZG9jdW1lbnQiLCJyZWFkeSIsImZpcnN0IiwiaHRtbCIsIm9uIiwicm93IiwiJG5ld1JvdyIsImFwcGVuZCIsImZpbmQiLCJjbG9zZXN0IiwicmVtb3ZlIl0sInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvb3BuYW1lcy9jcmVhdGUuanM/NWVlZiJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBwcm9kdWN0VXJsID0gJChcIiNwcm9kdWN0LWNvbnRhaW5lclwiKS5kYXRhKFwidXJsXCIpO1xuXG5mdW5jdGlvbiBjcmVhdGVQcm9kdWN0U2VsZWN0T3B0aW9ucyhjYWxsYmFjaykge1xuICAgICQuYWpheCh7XG4gICAgICAgIHVybDogcHJvZHVjdFVybCxcbiAgICAgICAgbWV0aG9kOiBcIkdFVFwiLFxuICAgICAgICBzdWNjZXNzOiBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgICAgbGV0IG9wdGlvbnMgPSAnPG9wdGlvbiB2YWx1ZT1cIlwiPlBpbGloIFByb2R1azwvb3B0aW9uPic7XG4gICAgICAgICAgICBkYXRhLmZvckVhY2goKHByb2R1Y3QpID0+IHtcbiAgICAgICAgICAgICAgICBvcHRpb25zICs9IGA8b3B0aW9uIHZhbHVlPVwiJHtwcm9kdWN0LmlkfVwiPiR7cHJvZHVjdC5uYW1lfTwvb3B0aW9uPmA7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGNhbGxiYWNrKG9wdGlvbnMpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYWxlcnQoXCJHYWdhbCBtZW11YXQgcHJvZHVrLlwiKTtcbiAgICAgICAgfSxcbiAgICB9KTtcbn1cblxuJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24gKCkge1xuICAgIC8vIEluaXRpYWwgbG9hZCBvbmx5IGZvciB0aGUgZmlyc3Qgcm93XG4gICAgY3JlYXRlUHJvZHVjdFNlbGVjdE9wdGlvbnMoKG9wdGlvbnMpID0+IHtcbiAgICAgICAgJChcIi5wcm9kdWN0LXNlbGVjdFwiKS5maXJzdCgpLmh0bWwob3B0aW9ucyk7XG4gICAgfSk7XG5cbiAgICAvLyBXaGVuIGFkZGluZyBhIG5ldyByb3dcbiAgICAkKGRvY3VtZW50KS5vbihcImNsaWNrXCIsIFwiLmJ0bi1hZGQtcm93XCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc3Qgcm93ID0gYFxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXJvdyBhbGlnbi1pdGVtcy1lbmQgcHJvZHVjdC1yb3dcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwIGNvbC1tZC00XCI+XG4gICAgICAgICAgICAgIDxzZWxlY3QgbmFtZT1cInByb2R1Y3RbXVwiIGNsYXNzPVwiZm9ybS1jb250cm9sIHByb2R1Y3Qtc2VsZWN0XCI+XG4gICAgICAgICAgICAgICAgPG9wdGlvbj5Mb2FkaW5nLi4uPC9vcHRpb24+XG4gICAgICAgICAgICAgIDwvc2VsZWN0PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBjb2wtbWQtM1wiPlxuICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInRleHRcIiBuYW1lPVwic3lzdGVtX3F1YW50aXR5W11cIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIHBsYWNlaG9sZGVyPVwiU3RvayBzaXN0ZW1cIj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXAgY29sLW1kLTNcIj5cbiAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgbmFtZT1cInBoeXNpY2FsX3F1YW50aXR5W11cIiBjbGFzcz1cImZvcm0tY29udHJvbFwiIHBsYWNlaG9sZGVyPVwiU3RvayBmaXNpa1wiPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cCBjb2wtbWQtMlwiPlxuICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tZGFuZ2VyIGJ0bi1yZW1vdmUtcm93XCI+PGkgY2xhc3M9XCJmbGF0aWNvbjItZGVsZXRlXCI+PC9pPjwvYnV0dG9uPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIGA7XG5cbiAgICAgICAgY29uc3QgJG5ld1JvdyA9ICQocm93KTtcbiAgICAgICAgJChcIiNwcm9kdWN0LWNvbnRhaW5lclwiKS5hcHBlbmQoJG5ld1Jvdyk7XG5cbiAgICAgICAgLy8gTG9hZCBvcHRpb25zIG9ubHkgZm9yIHRoZSBuZXcgc2VsZWN0XG4gICAgICAgIGNyZWF0ZVByb2R1Y3RTZWxlY3RPcHRpb25zKChvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAkbmV3Um93LmZpbmQoXCIucHJvZHVjdC1zZWxlY3RcIikuaHRtbChvcHRpb25zKTtcbiAgICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBSZW1vdmUgcm93XG4gICAgJChkb2N1bWVudCkub24oXCJjbGlja1wiLCBcIi5idG4tcmVtb3ZlLXJvd1wiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQodGhpcykuY2xvc2VzdChcIi5wcm9kdWN0LXJvd1wiKS5yZW1vdmUoKTtcbiAgICB9KTtcbn0pO1xuIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFNQSxVQUFVLEdBQUdDLENBQUMsQ0FBQyxvQkFBRCxDQUFELENBQXdCQyxJQUF4QixDQUE2QixLQUE3QixDQUFuQjs7QUFFQSxTQUFTQywwQkFBVCxDQUFvQ0MsUUFBcEMsRUFBOEM7RUFDMUNILENBQUMsQ0FBQ0ksSUFBRixDQUFPO0lBQ0hDLEdBQUcsRUFBRU4sVUFERjtJQUVITyxNQUFNLEVBQUUsS0FGTDtJQUdIQyxPQUFPLEVBQUUsaUJBQVVOLElBQVYsRUFBZ0I7TUFDckIsSUFBSU8sT0FBTyxHQUFHLHdDQUFkO01BQ0FQLElBQUksQ0FBQ1EsT0FBTCxDQUFhLFVBQUNDLE9BQUQsRUFBYTtRQUN0QkYsT0FBTyw4QkFBc0JFLE9BQU8sQ0FBQ0MsRUFBOUIsZ0JBQXFDRCxPQUFPLENBQUNFLElBQTdDLGNBQVA7TUFDSCxDQUZEO01BR0FULFFBQVEsQ0FBQ0ssT0FBRCxDQUFSO0lBQ0gsQ0FURTtJQVVISyxLQUFLLEVBQUUsaUJBQVk7TUFDZkMsS0FBSyxDQUFDLHNCQUFELENBQUw7SUFDSDtFQVpFLENBQVA7QUFjSDs7QUFFRGQsQ0FBQyxDQUFDZSxRQUFELENBQUQsQ0FBWUMsS0FBWixDQUFrQixZQUFZO0VBQzFCO0VBQ0FkLDBCQUEwQixDQUFDLFVBQUNNLE9BQUQsRUFBYTtJQUNwQ1IsQ0FBQyxDQUFDLGlCQUFELENBQUQsQ0FBcUJpQixLQUFyQixHQUE2QkMsSUFBN0IsQ0FBa0NWLE9BQWxDO0VBQ0gsQ0FGeUIsQ0FBMUIsQ0FGMEIsQ0FNMUI7O0VBQ0FSLENBQUMsQ0FBQ2UsUUFBRCxDQUFELENBQVlJLEVBQVosQ0FBZSxPQUFmLEVBQXdCLGNBQXhCLEVBQXdDLFlBQVk7SUFDaEQsSUFBTUMsR0FBRyw4MkJBQVQ7SUFtQkEsSUFBTUMsT0FBTyxHQUFHckIsQ0FBQyxDQUFDb0IsR0FBRCxDQUFqQjtJQUNBcEIsQ0FBQyxDQUFDLG9CQUFELENBQUQsQ0FBd0JzQixNQUF4QixDQUErQkQsT0FBL0IsRUFyQmdELENBdUJoRDs7SUFDQW5CLDBCQUEwQixDQUFDLFVBQUNNLE9BQUQsRUFBYTtNQUNwQ2EsT0FBTyxDQUFDRSxJQUFSLENBQWEsaUJBQWIsRUFBZ0NMLElBQWhDLENBQXFDVixPQUFyQztJQUNILENBRnlCLENBQTFCO0VBR0gsQ0EzQkQsRUFQMEIsQ0FvQzFCOztFQUNBUixDQUFDLENBQUNlLFFBQUQsQ0FBRCxDQUFZSSxFQUFaLENBQWUsT0FBZixFQUF3QixpQkFBeEIsRUFBMkMsWUFBWTtJQUNuRG5CLENBQUMsQ0FBQyxJQUFELENBQUQsQ0FBUXdCLE9BQVIsQ0FBZ0IsY0FBaEIsRUFBZ0NDLE1BQWhDO0VBQ0gsQ0FGRDtBQUdILENBeENEIn0=\n//# sourceURL=webpack-internal:///./resources/js/warehouse_management/opnames/create.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/opnames/create.js"]();
+/******/
+/******/ })()
+;
\ No newline at end of file
diff --git a/public/js/warehouse_management/opnames/index.js b/public/js/warehouse_management/opnames/index.js
index 7165d83..c6da8b8 100644
--- a/public/js/warehouse_management/opnames/index.js
+++ b/public/js/warehouse_management/opnames/index.js
@@ -15,7 +15,7 @@
\************************************************************/
/***/ (() => {
-eval("$.ajaxSetup({\n headers: {\n \"X-CSRF-TOKEN\": $('meta[name=\"csrf-token\"]').attr(\"content\")\n }\n});\nvar tableContainer = $(\"#opnames-table\");\nvar url = tableContainer.data(\"url\");\nvar table = $(\"#opnames-table\").DataTable({\n processing: true,\n serverSide: true,\n ajax: url,\n columns: [{\n data: \"dealer_name\",\n name: \"dealer.name\"\n }, {\n data: \"user_name\",\n name: \"user.name\"\n }, {\n data: \"opname_date\",\n name: \"opname_date\"\n }, {\n data: \"action\",\n name: \"action\",\n orderable: false,\n searchable: false\n }]\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvb3BuYW1lcy9pbmRleC5qcyIsIm5hbWVzIjpbIiQiLCJhamF4U2V0dXAiLCJoZWFkZXJzIiwiYXR0ciIsInRhYmxlQ29udGFpbmVyIiwidXJsIiwiZGF0YSIsInRhYmxlIiwiRGF0YVRhYmxlIiwicHJvY2Vzc2luZyIsInNlcnZlclNpZGUiLCJhamF4IiwiY29sdW1ucyIsIm5hbWUiLCJvcmRlcmFibGUiLCJzZWFyY2hhYmxlIl0sInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvb3BuYW1lcy9pbmRleC5qcz9hNGM4Il0sInNvdXJjZXNDb250ZW50IjpbIiQuYWpheFNldHVwKHtcbiAgICBoZWFkZXJzOiB7XG4gICAgICAgIFwiWC1DU1JGLVRPS0VOXCI6ICQoJ21ldGFbbmFtZT1cImNzcmYtdG9rZW5cIl0nKS5hdHRyKFwiY29udGVudFwiKSxcbiAgICB9LFxufSk7XG5sZXQgdGFibGVDb250YWluZXIgPSAkKFwiI29wbmFtZXMtdGFibGVcIik7XG5sZXQgdXJsID0gdGFibGVDb250YWluZXIuZGF0YShcInVybFwiKTtcbmxldCB0YWJsZSA9ICQoXCIjb3BuYW1lcy10YWJsZVwiKS5EYXRhVGFibGUoe1xuICAgIHByb2Nlc3Npbmc6IHRydWUsXG4gICAgc2VydmVyU2lkZTogdHJ1ZSxcbiAgICBhamF4OiB1cmwsXG4gICAgY29sdW1uczogW1xuICAgICAgICB7IGRhdGE6IFwiZGVhbGVyX25hbWVcIiwgbmFtZTogXCJkZWFsZXIubmFtZVwiIH0sXG4gICAgICAgIHsgZGF0YTogXCJ1c2VyX25hbWVcIiwgbmFtZTogXCJ1c2VyLm5hbWVcIiB9LFxuICAgICAgICB7IGRhdGE6IFwib3BuYW1lX2RhdGVcIiwgbmFtZTogXCJvcG5hbWVfZGF0ZVwiIH0sXG4gICAgICAgIHsgZGF0YTogXCJhY3Rpb25cIiwgbmFtZTogXCJhY3Rpb25cIiwgb3JkZXJhYmxlOiBmYWxzZSwgc2VhcmNoYWJsZTogZmFsc2UgfSxcbiAgICBdLFxufSk7XG4iXSwibWFwcGluZ3MiOiJBQUFBQSxDQUFDLENBQUNDLFNBQUYsQ0FBWTtFQUNSQyxPQUFPLEVBQUU7SUFDTCxnQkFBZ0JGLENBQUMsQ0FBQyx5QkFBRCxDQUFELENBQTZCRyxJQUE3QixDQUFrQyxTQUFsQztFQURYO0FBREQsQ0FBWjtBQUtBLElBQUlDLGNBQWMsR0FBR0osQ0FBQyxDQUFDLGdCQUFELENBQXRCO0FBQ0EsSUFBSUssR0FBRyxHQUFHRCxjQUFjLENBQUNFLElBQWYsQ0FBb0IsS0FBcEIsQ0FBVjtBQUNBLElBQUlDLEtBQUssR0FBR1AsQ0FBQyxDQUFDLGdCQUFELENBQUQsQ0FBb0JRLFNBQXBCLENBQThCO0VBQ3RDQyxVQUFVLEVBQUUsSUFEMEI7RUFFdENDLFVBQVUsRUFBRSxJQUYwQjtFQUd0Q0MsSUFBSSxFQUFFTixHQUhnQztFQUl0Q08sT0FBTyxFQUFFLENBQ0w7SUFBRU4sSUFBSSxFQUFFLGFBQVI7SUFBdUJPLElBQUksRUFBRTtFQUE3QixDQURLLEVBRUw7SUFBRVAsSUFBSSxFQUFFLFdBQVI7SUFBcUJPLElBQUksRUFBRTtFQUEzQixDQUZLLEVBR0w7SUFBRVAsSUFBSSxFQUFFLGFBQVI7SUFBdUJPLElBQUksRUFBRTtFQUE3QixDQUhLLEVBSUw7SUFBRVAsSUFBSSxFQUFFLFFBQVI7SUFBa0JPLElBQUksRUFBRSxRQUF4QjtJQUFrQ0MsU0FBUyxFQUFFLEtBQTdDO0lBQW9EQyxVQUFVLEVBQUU7RUFBaEUsQ0FKSztBQUo2QixDQUE5QixDQUFaIn0=\n//# sourceURL=webpack-internal:///./resources/js/warehouse_management/opnames/index.js\n");
+eval("$.ajaxSetup({\n headers: {\n \"X-CSRF-TOKEN\": $('meta[name=\"csrf-token\"]').attr(\"content\")\n }\n});\nvar tableContainer = $(\"#opnames-table\");\nvar url = tableContainer.data(\"url\");\nvar table = $(\"#opnames-table\").DataTable({\n processing: true,\n serverSide: true,\n ajax: url,\n columns: [{\n data: \"dealer_name\",\n name: \"dealer.name\"\n }, {\n data: \"user_name\",\n name: \"user.name\"\n }, {\n data: \"opname_date\",\n name: \"opname_date\"\n }, {\n data: \"action\",\n name: \"action\",\n orderable: false,\n searchable: false\n }]\n});\n$(document).on(\"click\", \".btn-product-stock-dealers\", function () {\n var productId = $(this).data(\"id\");\n var productName = $(this).data(\"name\");\n var ajaxUrl = $(this).data(\"url\"); // Set product name in modal title\n\n $(\"#product-name-title\").text(productName); // Initialize or reload DataTable inside modal\n\n $(\"#dealer-stock-table\").DataTable({\n destroy: true,\n // reinit if exists\n processing: true,\n serverSide: true,\n ajax: {\n url: ajaxUrl,\n data: {\n product_id: productId\n }\n },\n columns: [{\n data: \"dealer_name\",\n name: \"dealer_name\"\n }, {\n data: \"system_stock\",\n name: \"system_stock\"\n }, {\n data: \"physical_stock\",\n name: \"physical_stock\"\n }, {\n data: \"difference\",\n name: \"difference\"\n }, {\n data: \"opname_date\",\n name: \"opname_date\"\n }]\n }); // Show the modal\n\n $(\"#dealerStockModal\").modal(\"show\");\n});//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvb3BuYW1lcy9pbmRleC5qcyIsIm5hbWVzIjpbIiQiLCJhamF4U2V0dXAiLCJoZWFkZXJzIiwiYXR0ciIsInRhYmxlQ29udGFpbmVyIiwidXJsIiwiZGF0YSIsInRhYmxlIiwiRGF0YVRhYmxlIiwicHJvY2Vzc2luZyIsInNlcnZlclNpZGUiLCJhamF4IiwiY29sdW1ucyIsIm5hbWUiLCJvcmRlcmFibGUiLCJzZWFyY2hhYmxlIiwiZG9jdW1lbnQiLCJvbiIsInByb2R1Y3RJZCIsInByb2R1Y3ROYW1lIiwiYWpheFVybCIsInRleHQiLCJkZXN0cm95IiwicHJvZHVjdF9pZCIsIm1vZGFsIl0sInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9yZXNvdXJjZXMvanMvd2FyZWhvdXNlX21hbmFnZW1lbnQvb3BuYW1lcy9pbmRleC5qcz9hNGM4Il0sInNvdXJjZXNDb250ZW50IjpbIiQuYWpheFNldHVwKHtcbiAgICBoZWFkZXJzOiB7XG4gICAgICAgIFwiWC1DU1JGLVRPS0VOXCI6ICQoJ21ldGFbbmFtZT1cImNzcmYtdG9rZW5cIl0nKS5hdHRyKFwiY29udGVudFwiKSxcbiAgICB9LFxufSk7XG5sZXQgdGFibGVDb250YWluZXIgPSAkKFwiI29wbmFtZXMtdGFibGVcIik7XG5sZXQgdXJsID0gdGFibGVDb250YWluZXIuZGF0YShcInVybFwiKTtcbmxldCB0YWJsZSA9ICQoXCIjb3BuYW1lcy10YWJsZVwiKS5EYXRhVGFibGUoe1xuICAgIHByb2Nlc3Npbmc6IHRydWUsXG4gICAgc2VydmVyU2lkZTogdHJ1ZSxcbiAgICBhamF4OiB1cmwsXG4gICAgY29sdW1uczogW1xuICAgICAgICB7IGRhdGE6IFwiZGVhbGVyX25hbWVcIiwgbmFtZTogXCJkZWFsZXIubmFtZVwiIH0sXG4gICAgICAgIHsgZGF0YTogXCJ1c2VyX25hbWVcIiwgbmFtZTogXCJ1c2VyLm5hbWVcIiB9LFxuICAgICAgICB7IGRhdGE6IFwib3BuYW1lX2RhdGVcIiwgbmFtZTogXCJvcG5hbWVfZGF0ZVwiIH0sXG4gICAgICAgIHsgZGF0YTogXCJhY3Rpb25cIiwgbmFtZTogXCJhY3Rpb25cIiwgb3JkZXJhYmxlOiBmYWxzZSwgc2VhcmNoYWJsZTogZmFsc2UgfSxcbiAgICBdLFxufSk7XG4kKGRvY3VtZW50KS5vbihcImNsaWNrXCIsIFwiLmJ0bi1wcm9kdWN0LXN0b2NrLWRlYWxlcnNcIiwgZnVuY3Rpb24gKCkge1xuICAgIGNvbnN0IHByb2R1Y3RJZCA9ICQodGhpcykuZGF0YShcImlkXCIpO1xuICAgIGNvbnN0IHByb2R1Y3ROYW1lID0gJCh0aGlzKS5kYXRhKFwibmFtZVwiKTtcbiAgICBjb25zdCBhamF4VXJsID0gJCh0aGlzKS5kYXRhKFwidXJsXCIpO1xuXG4gICAgLy8gU2V0IHByb2R1Y3QgbmFtZSBpbiBtb2RhbCB0aXRsZVxuICAgICQoXCIjcHJvZHVjdC1uYW1lLXRpdGxlXCIpLnRleHQocHJvZHVjdE5hbWUpO1xuXG4gICAgLy8gSW5pdGlhbGl6ZSBvciByZWxvYWQgRGF0YVRhYmxlIGluc2lkZSBtb2RhbFxuICAgICQoXCIjZGVhbGVyLXN0b2NrLXRhYmxlXCIpLkRhdGFUYWJsZSh7XG4gICAgICAgIGRlc3Ryb3k6IHRydWUsIC8vIHJlaW5pdCBpZiBleGlzdHNcbiAgICAgICAgcHJvY2Vzc2luZzogdHJ1ZSxcbiAgICAgICAgc2VydmVyU2lkZTogdHJ1ZSxcbiAgICAgICAgYWpheDoge1xuICAgICAgICAgICAgdXJsOiBhamF4VXJsLFxuICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgIHByb2R1Y3RfaWQ6IHByb2R1Y3RJZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGNvbHVtbnM6IFtcbiAgICAgICAgICAgIHsgZGF0YTogXCJkZWFsZXJfbmFtZVwiLCBuYW1lOiBcImRlYWxlcl9uYW1lXCIgfSxcbiAgICAgICAgICAgIHsgZGF0YTogXCJzeXN0ZW1fc3RvY2tcIiwgbmFtZTogXCJzeXN0ZW1fc3RvY2tcIiB9LFxuICAgICAgICAgICAgeyBkYXRhOiBcInBoeXNpY2FsX3N0b2NrXCIsIG5hbWU6IFwicGh5c2ljYWxfc3RvY2tcIiB9LFxuICAgICAgICAgICAgeyBkYXRhOiBcImRpZmZlcmVuY2VcIiwgbmFtZTogXCJkaWZmZXJlbmNlXCIgfSxcbiAgICAgICAgICAgIHsgZGF0YTogXCJvcG5hbWVfZGF0ZVwiLCBuYW1lOiBcIm9wbmFtZV9kYXRlXCIgfSxcbiAgICAgICAgXSxcbiAgICB9KTtcblxuICAgIC8vIFNob3cgdGhlIG1vZGFsXG4gICAgJChcIiNkZWFsZXJTdG9ja01vZGFsXCIpLm1vZGFsKFwic2hvd1wiKTtcbn0pO1xuIl0sIm1hcHBpbmdzIjoiQUFBQUEsQ0FBQyxDQUFDQyxTQUFGLENBQVk7RUFDUkMsT0FBTyxFQUFFO0lBQ0wsZ0JBQWdCRixDQUFDLENBQUMseUJBQUQsQ0FBRCxDQUE2QkcsSUFBN0IsQ0FBa0MsU0FBbEM7RUFEWDtBQURELENBQVo7QUFLQSxJQUFJQyxjQUFjLEdBQUdKLENBQUMsQ0FBQyxnQkFBRCxDQUF0QjtBQUNBLElBQUlLLEdBQUcsR0FBR0QsY0FBYyxDQUFDRSxJQUFmLENBQW9CLEtBQXBCLENBQVY7QUFDQSxJQUFJQyxLQUFLLEdBQUdQLENBQUMsQ0FBQyxnQkFBRCxDQUFELENBQW9CUSxTQUFwQixDQUE4QjtFQUN0Q0MsVUFBVSxFQUFFLElBRDBCO0VBRXRDQyxVQUFVLEVBQUUsSUFGMEI7RUFHdENDLElBQUksRUFBRU4sR0FIZ0M7RUFJdENPLE9BQU8sRUFBRSxDQUNMO0lBQUVOLElBQUksRUFBRSxhQUFSO0lBQXVCTyxJQUFJLEVBQUU7RUFBN0IsQ0FESyxFQUVMO0lBQUVQLElBQUksRUFBRSxXQUFSO0lBQXFCTyxJQUFJLEVBQUU7RUFBM0IsQ0FGSyxFQUdMO0lBQUVQLElBQUksRUFBRSxhQUFSO0lBQXVCTyxJQUFJLEVBQUU7RUFBN0IsQ0FISyxFQUlMO0lBQUVQLElBQUksRUFBRSxRQUFSO0lBQWtCTyxJQUFJLEVBQUUsUUFBeEI7SUFBa0NDLFNBQVMsRUFBRSxLQUE3QztJQUFvREMsVUFBVSxFQUFFO0VBQWhFLENBSks7QUFKNkIsQ0FBOUIsQ0FBWjtBQVdBZixDQUFDLENBQUNnQixRQUFELENBQUQsQ0FBWUMsRUFBWixDQUFlLE9BQWYsRUFBd0IsNEJBQXhCLEVBQXNELFlBQVk7RUFDOUQsSUFBTUMsU0FBUyxHQUFHbEIsQ0FBQyxDQUFDLElBQUQsQ0FBRCxDQUFRTSxJQUFSLENBQWEsSUFBYixDQUFsQjtFQUNBLElBQU1hLFdBQVcsR0FBR25CLENBQUMsQ0FBQyxJQUFELENBQUQsQ0FBUU0sSUFBUixDQUFhLE1BQWIsQ0FBcEI7RUFDQSxJQUFNYyxPQUFPLEdBQUdwQixDQUFDLENBQUMsSUFBRCxDQUFELENBQVFNLElBQVIsQ0FBYSxLQUFiLENBQWhCLENBSDhELENBSzlEOztFQUNBTixDQUFDLENBQUMscUJBQUQsQ0FBRCxDQUF5QnFCLElBQXpCLENBQThCRixXQUE5QixFQU44RCxDQVE5RDs7RUFDQW5CLENBQUMsQ0FBQyxxQkFBRCxDQUFELENBQXlCUSxTQUF6QixDQUFtQztJQUMvQmMsT0FBTyxFQUFFLElBRHNCO0lBQ2hCO0lBQ2ZiLFVBQVUsRUFBRSxJQUZtQjtJQUcvQkMsVUFBVSxFQUFFLElBSG1CO0lBSS9CQyxJQUFJLEVBQUU7TUFDRk4sR0FBRyxFQUFFZSxPQURIO01BRUZkLElBQUksRUFBRTtRQUNGaUIsVUFBVSxFQUFFTDtNQURWO0lBRkosQ0FKeUI7SUFVL0JOLE9BQU8sRUFBRSxDQUNMO01BQUVOLElBQUksRUFBRSxhQUFSO01BQXVCTyxJQUFJLEVBQUU7SUFBN0IsQ0FESyxFQUVMO01BQUVQLElBQUksRUFBRSxjQUFSO01BQXdCTyxJQUFJLEVBQUU7SUFBOUIsQ0FGSyxFQUdMO01BQUVQLElBQUksRUFBRSxnQkFBUjtNQUEwQk8sSUFBSSxFQUFFO0lBQWhDLENBSEssRUFJTDtNQUFFUCxJQUFJLEVBQUUsWUFBUjtNQUFzQk8sSUFBSSxFQUFFO0lBQTVCLENBSkssRUFLTDtNQUFFUCxJQUFJLEVBQUUsYUFBUjtNQUF1Qk8sSUFBSSxFQUFFO0lBQTdCLENBTEs7RUFWc0IsQ0FBbkMsRUFUOEQsQ0E0QjlEOztFQUNBYixDQUFDLENBQUMsbUJBQUQsQ0FBRCxDQUF1QndCLEtBQXZCLENBQTZCLE1BQTdCO0FBQ0gsQ0E5QkQifQ==\n//# sourceURL=webpack-internal:///./resources/js/warehouse_management/opnames/index.js\n");
/***/ })
diff --git a/public/mix-manifest.json b/public/mix-manifest.json
index 5267aa1..bc8e6b0 100644
--- a/public/mix-manifest.json
+++ b/public/mix-manifest.json
@@ -5,5 +5,6 @@
"/js/warehouse_management/products/create.js": "/js/warehouse_management/products/create.js",
"/js/warehouse_management/products/edit.js": "/js/warehouse_management/products/edit.js",
"/js/warehouse_management/opnames/index.js": "/js/warehouse_management/opnames/index.js",
+ "/js/warehouse_management/opnames/create.js": "/js/warehouse_management/opnames/create.js",
"/css/app.css": "/css/app.css"
}
diff --git a/resources/js/warehouse_management/opnames/create.js b/resources/js/warehouse_management/opnames/create.js
new file mode 100644
index 0000000..d186f6d
--- /dev/null
+++ b/resources/js/warehouse_management/opnames/create.js
@@ -0,0 +1,60 @@
+const productUrl = $("#product-container").data("url");
+
+function createProductSelectOptions(callback) {
+ $.ajax({
+ url: productUrl,
+ method: "GET",
+ success: function (data) {
+ let options = '';
+ data.forEach((product) => {
+ options += ``;
+ });
+ callback(options);
+ },
+ error: function () {
+ alert("Gagal memuat produk.");
+ },
+ });
+}
+
+$(document).ready(function () {
+ // Initial load only for the first row
+ createProductSelectOptions((options) => {
+ $(".product-select").first().html(options);
+ });
+
+ // When adding a new row
+ $(document).on("click", ".btn-add-row", function () {
+ const row = `
+
+ `;
+
+ const $newRow = $(row);
+ $("#product-container").append($newRow);
+
+ // Load options only for the new select
+ createProductSelectOptions((options) => {
+ $newRow.find(".product-select").html(options);
+ });
+ });
+
+ // Remove row
+ $(document).on("click", ".btn-remove-row", function () {
+ $(this).closest(".product-row").remove();
+ });
+});
diff --git a/resources/js/warehouse_management/opnames/index.js b/resources/js/warehouse_management/opnames/index.js
index e46f378..7633649 100644
--- a/resources/js/warehouse_management/opnames/index.js
+++ b/resources/js/warehouse_management/opnames/index.js
@@ -16,3 +16,34 @@ let table = $("#opnames-table").DataTable({
{ data: "action", name: "action", orderable: false, searchable: false },
],
});
+$(document).on("click", ".btn-product-stock-dealers", function () {
+ const productId = $(this).data("id");
+ const productName = $(this).data("name");
+ const ajaxUrl = $(this).data("url");
+
+ // Set product name in modal title
+ $("#product-name-title").text(productName);
+
+ // Initialize or reload DataTable inside modal
+ $("#dealer-stock-table").DataTable({
+ destroy: true, // reinit if exists
+ processing: true,
+ serverSide: true,
+ ajax: {
+ url: ajaxUrl,
+ data: {
+ product_id: productId,
+ },
+ },
+ columns: [
+ { data: "dealer_name", name: "dealer_name" },
+ { data: "system_stock", name: "system_stock" },
+ { data: "physical_stock", name: "physical_stock" },
+ { data: "difference", name: "difference" },
+ { data: "opname_date", name: "opname_date" },
+ ],
+ });
+
+ // Show the modal
+ $("#dealerStockModal").modal("show");
+});
diff --git a/resources/views/layouts/partials/header.blade.php b/resources/views/layouts/partials/header.blade.php
index 782cf23..25903bd 100644
--- a/resources/views/layouts/partials/header.blade.php
+++ b/resources/views/layouts/partials/header.blade.php
@@ -19,7 +19,7 @@
@@ -27,7 +27,7 @@
- John Doe
+ {{ Auth::user()->name ?? '' }}
diff --git a/resources/views/warehouse_management/opnames/create.blade.php b/resources/views/warehouse_management/opnames/create.blade.php
index e69de29..0653b61 100644
--- a/resources/views/warehouse_management/opnames/create.blade.php
+++ b/resources/views/warehouse_management/opnames/create.blade.php
@@ -0,0 +1,59 @@
+@extends('layouts.backapp')
+
+@section('content')
+
+
+
+
+
+
+
Tambah Opnames
+
+
+
+
+
+@endsection
+
+@section('javascripts')
+
+@endsection
diff --git a/resources/views/warehouse_management/opnames/index.blade.php b/resources/views/warehouse_management/opnames/index.blade.php
index 6518c3c..9a817a7 100644
--- a/resources/views/warehouse_management/opnames/index.blade.php
+++ b/resources/views/warehouse_management/opnames/index.blade.php
@@ -39,6 +39,34 @@
+
+
+
+
+
+
+
+
+
+ | Dealer |
+ System Stock |
+ Physical Stock |
+ Difference |
+ Opname Date |
+
+
+
+
+
+
+
+
+
@endsection
@section('javascripts')
diff --git a/routes/web.php b/routes/web.php
index bc319cd..1957073 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -211,6 +211,8 @@ Route::group(['middleware' => 'auth'], function() {
Route::get('/', 'index')->name('products.index');
Route::get('create', 'create')->name('products.create');
Route::post('/', 'store')->name('products.store');
+ Route::get('all','all_products')->name('products.all');
+ Route::get('dealers-stock')->name('products.dealers_stock');
Route::get('{product}', 'show')->name('products.show');
Route::get('{product}/edit', 'edit')->name('products.edit');
Route::put('{product}', 'update')->name('products.update');
@@ -233,6 +235,7 @@ Route::group(['middleware' => 'auth'], function() {
Route::prefix('opnames')->controller(OpnamesController::class)->group(function (){
Route::get('/','index')->name('opnames.index');
Route::get('create','create')->name('opnames.create');
+ Route::post('/','store')->name('opnames.store');
});
});
});
diff --git a/webpack.mix.js b/webpack.mix.js
index b58f527..c627e4b 100644
--- a/webpack.mix.js
+++ b/webpack.mix.js
@@ -33,6 +33,10 @@ mix.js("resources/js/app.js", "public/js")
"resources/js/warehouse_management/opnames/index.js",
"public/js/warehouse_management/opnames"
)
+ .js(
+ "resources/js/warehouse_management/opnames/create.js",
+ "public/js/warehouse_management/opnames"
+ )
.sourceMaps();
mix.browserSync({