partial update products
This commit is contained in:
@@ -126,7 +126,7 @@ class ProductCategoriesController extends Controller
|
|||||||
return response()->json(['success' => true, 'message' => 'Kategorii berhasil dihapus.']);
|
return response()->json(['success' => true, 'message' => 'Kategorii berhasil dihapus.']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getParents(Request $request)
|
public function product_category_parents(Request $request)
|
||||||
{
|
{
|
||||||
$parents = ProductCategory::whereNull('parent_id')->get(['id', 'name']);
|
$parents = ProductCategory::whereNull('parent_id')->get(['id', 'name']);
|
||||||
return response()->json($parents);
|
return response()->json($parents);
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ use App\Models\Dealer;
|
|||||||
use App\Models\Menu;
|
use App\Models\Menu;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\ProductCategory;
|
use App\Models\ProductCategory;
|
||||||
use App\Models\StockMutation;
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Yajra\DataTables\Facades\DataTables;
|
use Yajra\DataTables\Facades\DataTables;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
@@ -49,8 +49,10 @@ class ProductsController extends Controller
|
|||||||
|
|
||||||
$btn .= '<button class="btn btn-sm btn-toggle-active '
|
$btn .= '<button class="btn btn-sm btn-toggle-active '
|
||||||
. ($row->active ? 'btn-danger' : 'btn-success') . '"
|
. ($row->active ? 'btn-danger' : 'btn-success') . '"
|
||||||
data-url="' . route('products.toggleActive', $row->id) . '" data-active="'.$row->active.'">'
|
data-url="' . route('products.toggleActive', $row->id) . '" data-active="'.$row->active.'" style="margin-right: 8px;">'
|
||||||
. ($row->active ? 'Nonaktifkan' : 'Aktifkan') . '</button>';
|
. ($row->active ? 'Nonaktifkan' : 'Aktifkan') . '</button>';
|
||||||
|
|
||||||
|
$btn .= '<button class="btn btn-sm btn-secondary btn-product-stock-dealers">Stock</button>';
|
||||||
|
|
||||||
$btn .= '</div>';
|
$btn .= '</div>';
|
||||||
|
|
||||||
@@ -93,10 +95,7 @@ class ProductsController extends Controller
|
|||||||
'description' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
'unit' => 'nullable|string',
|
'unit' => 'nullable|string',
|
||||||
'active' => 'required|boolean',
|
'active' => 'required|boolean',
|
||||||
'product_category_id' => 'required|exists:product_categories,id',
|
'product_category_id' => 'required|exists:product_categories,id'
|
||||||
'dealer_stock' => 'nullable|array',
|
|
||||||
'dealer_stock.*.dealer_id' => 'required|exists:dealers,id',
|
|
||||||
'dealer_stock.*.quantity' => 'required|integer|min:0',
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Create product
|
// Create product
|
||||||
@@ -108,34 +107,6 @@ class ProductsController extends Controller
|
|||||||
'description' => $request->description,
|
'description' => $request->description,
|
||||||
'product_category_id' => $request->product_category_id,
|
'product_category_id' => $request->product_category_id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Prepare dealer stock for pivot and create mutation records
|
|
||||||
$pivotData = [];
|
|
||||||
if ($request->has('dealer_stock')) {
|
|
||||||
foreach ($request->dealer_stock as $stockData) {
|
|
||||||
if (empty($stockData['dealer_id']) || !isset($stockData['quantity'])) continue;
|
|
||||||
|
|
||||||
$dealerId = $stockData['dealer_id'];
|
|
||||||
$quantity = $stockData['quantity'];
|
|
||||||
|
|
||||||
$pivotData[$dealerId] = ['quantity' => $quantity];
|
|
||||||
|
|
||||||
// Create stock mutation for initial stock "in"
|
|
||||||
StockMutation::create([
|
|
||||||
'product_id' => $product->id,
|
|
||||||
'dealer_id' => $dealerId,
|
|
||||||
'mutation_type' => 'in', // karena ini penambahan stok awal
|
|
||||||
'quantity' => $quantity,
|
|
||||||
'description' => 'Initial stock added when product created',
|
|
||||||
'user_id' => Auth::id(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach dealer stock using pivot table
|
|
||||||
$product->dealers()->attach($pivotData);
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('products.index')->with('success', 'Produk berhasil ditambahkan.');
|
return redirect()->route('products.index')->with('success', 'Produk berhasil ditambahkan.');
|
||||||
}catch(\Exception $ex){
|
}catch(\Exception $ex){
|
||||||
@@ -179,77 +150,26 @@ class ProductsController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function update(Request $request, Product $product)
|
public function update(Request $request, Product $product)
|
||||||
{
|
{
|
||||||
$request->validate([
|
try{
|
||||||
'code' => [
|
$request->validate([
|
||||||
'required',
|
'code' => [
|
||||||
'string',
|
'required',
|
||||||
Rule::unique('products')->ignore($product->id)->whereNull('deleted_at'),
|
'string',
|
||||||
],
|
Rule::unique('products')->ignore($product->id)->whereNull('deleted_at'),
|
||||||
'name' => 'required|string',
|
],
|
||||||
'description' => 'nullable|string',
|
'name' => 'required|string',
|
||||||
'unit' => 'nullable|string',
|
'description' => 'nullable|string',
|
||||||
'active' => 'required|boolean',
|
'unit' => 'nullable|string',
|
||||||
'product_category_id' => 'required|exists:product_categories,id',
|
'active' => 'required|boolean',
|
||||||
'dealer_stock' => 'nullable|array',
|
'product_category_id' => 'required|exists:product_categories,id'
|
||||||
'dealer_stock.*.dealer_id' => 'required|exists:dealers,id',
|
]);
|
||||||
'dealer_stock.*.quantity' => 'required|integer|min:0',
|
|
||||||
]);
|
$product->update($request->only(['code', 'name', 'description', 'unit','active', 'product_category_id']));
|
||||||
|
|
||||||
$product->update($request->only(['code', 'name', 'description', 'unit', 'product_category_id']));
|
return redirect()->route('products.index')->with('success', 'Produk berhasil diperbarui.');
|
||||||
|
}catch(\Exception $ex){
|
||||||
// Ambil stok lama dari pivot
|
Log::error($ex->getMessage());
|
||||||
$oldStocks = $product->dealers()->pluck('quantity', 'dealer_id')->toArray();
|
|
||||||
|
|
||||||
// Data baru untuk sync pivot
|
|
||||||
$syncData = [];
|
|
||||||
|
|
||||||
$newStocks = [];
|
|
||||||
if ($request->has('dealer_stock')) {
|
|
||||||
foreach ($request->dealer_stock as $item) {
|
|
||||||
$dealerId = $item['dealer_id'];
|
|
||||||
$newQty = $item['quantity'];
|
|
||||||
$syncData[$dealerId] = ['quantity' => $newQty];
|
|
||||||
$newStocks[$dealerId] = $newQty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync pivot table
|
|
||||||
$product->dealers()->sync($syncData);
|
|
||||||
|
|
||||||
// Hitung mutasi stok (selisih)
|
|
||||||
// Mutasi stok untuk stok baru atau perubahan stok
|
|
||||||
foreach ($newStocks as $dealerId => $newQty) {
|
|
||||||
$oldQty = $oldStocks[$dealerId] ?? 0;
|
|
||||||
$diff = $newQty - $oldQty;
|
|
||||||
|
|
||||||
if ($diff != 0) {
|
|
||||||
StockMutation::create([
|
|
||||||
'product_id' => $product->id,
|
|
||||||
'dealer_id' => $dealerId,
|
|
||||||
'mutation_type' => $diff > 0 ? 'in' : 'out',
|
|
||||||
'quantity' => abs($diff),
|
|
||||||
'description' => 'Stock updated via product update',
|
|
||||||
'user_id' => auth()->id(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mutasi stok untuk dealer yang dihapus (stok jadi 0)
|
|
||||||
$deletedDealers = array_diff_key($oldStocks, $newStocks);
|
|
||||||
foreach ($deletedDealers as $dealerId => $oldQty) {
|
|
||||||
if ($oldQty > 0) {
|
|
||||||
StockMutation::create([
|
|
||||||
'product_id' => $product->id,
|
|
||||||
'dealer_id' => $dealerId,
|
|
||||||
'mutation_type' => 'out',
|
|
||||||
'quantity' => $oldQty,
|
|
||||||
'description' => 'Stock removed via product update (dealer removed)',
|
|
||||||
'user_id' => auth()->id(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('products.index')->with('success', 'Produk berhasil diperbarui.');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,41 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\WarehouseManagement;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\StockMutation;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Yajra\DataTables\Facades\DataTables;
|
|
||||||
|
|
||||||
class StockMutationsController extends Controller
|
|
||||||
{
|
|
||||||
public function index(Request $request){
|
|
||||||
if ($request->ajax()) {
|
|
||||||
$query = StockMutation::with(['product', 'dealer', 'user']);
|
|
||||||
|
|
||||||
return DataTables::of($query)
|
|
||||||
->addIndexColumn()
|
|
||||||
->addColumn('product_name', function ($row) {
|
|
||||||
return $row->product ? $row->product->name : '-';
|
|
||||||
})
|
|
||||||
->addColumn('dealer_name', function ($row) {
|
|
||||||
return $row->dealer ? $row->dealer->name : '-';
|
|
||||||
})
|
|
||||||
->addColumn('user_name', function ($row) {
|
|
||||||
return $row->user ? $row->user->name : '-';
|
|
||||||
})
|
|
||||||
->addColumn('mutation_type_label', function ($row) {
|
|
||||||
return $row->mutation_type == 'in'
|
|
||||||
? '<span class="badge bg-success">Masuk</span>'
|
|
||||||
: '<span class="badge bg-danger">Keluar</span>';
|
|
||||||
})
|
|
||||||
->editColumn('created_at', function ($row) {
|
|
||||||
return $row->created_at->format('d M Y H:i');
|
|
||||||
})
|
|
||||||
->rawColumns(['mutation_type_label'])
|
|
||||||
->make(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('warehouse_management.stock_mutations.index');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\WarehouseManagement;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\StockOpname;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Yajra\DataTables\Facades\DataTables;
|
|
||||||
|
|
||||||
class StockOpnamesController extends Controller
|
|
||||||
{
|
|
||||||
public function index(Request $request){
|
|
||||||
try{
|
|
||||||
if ($request->ajax()) {
|
|
||||||
$query = StockOpname::with(['product', 'dealer', 'user']);
|
|
||||||
|
|
||||||
return DataTables::of($query)
|
|
||||||
->addIndexColumn()
|
|
||||||
->addColumn('product_name', function ($row) {
|
|
||||||
return $row->product ? $row->product->name : '-';
|
|
||||||
})
|
|
||||||
->addColumn('dealer_name', function ($row) {
|
|
||||||
return $row->dealer ? $row->dealer->name : '-';
|
|
||||||
})
|
|
||||||
->addColumn('user_name', function ($row) {
|
|
||||||
return $row->user ? $row->user->name : '-';
|
|
||||||
})
|
|
||||||
->editColumn('opname_date', function ($row) {
|
|
||||||
return $row->opname_date->format('d M Y');
|
|
||||||
})
|
|
||||||
->make(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return view('warehouse_management.stock_opnames.index');
|
|
||||||
}catch(\Exception $ex){
|
|
||||||
Log::error($ex->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Stock extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
protected $table = 'stock';
|
|
||||||
protected $fillable = [
|
|
||||||
'product_id',
|
|
||||||
'dealer_id',
|
|
||||||
'quantity',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function product()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Product::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dealer()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Dealer::class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class StockMutation extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'product_id',
|
|
||||||
'dealer_id',
|
|
||||||
'mutation_type',
|
|
||||||
'quantity',
|
|
||||||
'description',
|
|
||||||
'user_id',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function product()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Product::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dealer()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Dealer::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class StockOpname extends Model
|
|
||||||
{
|
|
||||||
use HasFactory;
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'product_id',
|
|
||||||
'dealer_id',
|
|
||||||
'system_quantity',
|
|
||||||
'physical_quantity',
|
|
||||||
'difference',
|
|
||||||
'opname_date',
|
|
||||||
'user_id',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function product()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Product::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dealer()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Dealer::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,6 +16,7 @@ class CreateProductCategoriesTable extends Migration
|
|||||||
Schema::create('product_categories', function (Blueprint $table) {
|
Schema::create('product_categories', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
|
$table->foreignId('parent_id')->nullable()->constrained('product_categories')->nullOnDelete();
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ class CreateProductsTable extends Migration
|
|||||||
$table->id();
|
$table->id();
|
||||||
$table->string('code')->unique();
|
$table->string('code')->unique();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
|
$table->boolean('active')->default(true);
|
||||||
|
$table->string('unit')->nullable();
|
||||||
$table->text('description')->nullable();
|
$table->text('description')->nullable();
|
||||||
$table->foreignId('product_category_id')->constrained()->onDelete('cascade');
|
$table->foreignId('product_category_id')->constrained()->onDelete('cascade');
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class CreateStockTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('stock', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->foreignId('product_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->foreignId('dealer_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->integer('quantity')->default(0);
|
|
||||||
$table->timestamps();
|
|
||||||
|
|
||||||
$table->unique(['product_id','dealer_id']);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('stock');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AddParentIdToProductCategoriesTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('product_categories', function (Blueprint $table) {
|
|
||||||
$table->foreignId('parent_id')->nullable()->after('name')->constrained('product_categories')->nullOnDelete();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('product_categories', function (Blueprint $table) {
|
|
||||||
$table->dropForeign(['parent_id']);
|
|
||||||
$table->dropColumn('parent_id');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class CreateStockMutationsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('stock_mutations', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->foreignId('product_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->foreignId('dealer_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->enum('mutation_type',['in','out','adjustment']);
|
|
||||||
$table->integer('quantity');
|
|
||||||
$table->text('description')->nullable();
|
|
||||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('stock_mutations');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class CreateStockOpnamesTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::create('stock_opnames', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->foreignId('product_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->foreignId('dealer_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->integer('system_quantity');
|
|
||||||
$table->integer('physical_quantity');
|
|
||||||
$table->integer('difference');
|
|
||||||
$table->date('opname_date');
|
|
||||||
$table->foreignId('user_id')->constrained()->onDelete('cascade');
|
|
||||||
$table->timestamps();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('stock_opnames');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AddUnitToProductsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('products', function (Blueprint $table) {
|
|
||||||
$table->string('unit')->nullable()->after('description');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('products', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('unit');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class AddActiveToProductsTable extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('products', function (Blueprint $table) {
|
|
||||||
$table->boolean('active')->default(true)->after('unit');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function down()
|
|
||||||
{
|
|
||||||
Schema::table('products', function (Blueprint $table) {
|
|
||||||
$table->dropColumn('active');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
32
public/js/warehouse_management/stock_opnames/create.js
Normal file
32
public/js/warehouse_management/stock_opnames/create.js
Normal file
@@ -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_opnames/create.js":
|
||||||
|
/*!*******************************************************************!*\
|
||||||
|
!*** ./resources/js/warehouse_management/stock_opnames/create.js ***!
|
||||||
|
\*******************************************************************/
|
||||||
|
/***/ (() => {
|
||||||
|
|
||||||
|
eval("//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sInNvdXJjZXMiOlsid2VicGFjazovLy8uL3Jlc291cmNlcy9qcy93YXJlaG91c2VfbWFuYWdlbWVudC9zdG9ja19vcG5hbWVzL2NyZWF0ZS5qcz9kYzA1Il0sInNvdXJjZXNDb250ZW50IjpbIiJdLCJtYXBwaW5ncyI6IiIsImZpbGUiOiIuL3Jlc291cmNlcy9qcy93YXJlaG91c2VfbWFuYWdlbWVudC9zdG9ja19vcG5hbWVzL2NyZWF0ZS5qcyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./resources/js/warehouse_management/stock_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/stock_opnames/create.js"]();
|
||||||
|
/******/
|
||||||
|
/******/ })()
|
||||||
|
;
|
||||||
@@ -6,5 +6,6 @@
|
|||||||
"/js/warehouse_management/products/edit.js": "/js/warehouse_management/products/edit.js",
|
"/js/warehouse_management/products/edit.js": "/js/warehouse_management/products/edit.js",
|
||||||
"/js/warehouse_management/stock_mutations/index.js": "/js/warehouse_management/stock_mutations/index.js",
|
"/js/warehouse_management/stock_mutations/index.js": "/js/warehouse_management/stock_mutations/index.js",
|
||||||
"/js/warehouse_management/stock_opnames/index.js": "/js/warehouse_management/stock_opnames/index.js",
|
"/js/warehouse_management/stock_opnames/index.js": "/js/warehouse_management/stock_opnames/index.js",
|
||||||
|
"/js/warehouse_management/stock_opnames/create.js": "/js/warehouse_management/stock_opnames/create.js",
|
||||||
"/css/app.css": "/css/app.css"
|
"/css/app.css": "/css/app.css"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,8 +125,10 @@ $(document).on("click", ".btn-destroy-product-category", function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function loadParentCategories(selectedId = null) {
|
function loadParentCategories(selectedId = null) {
|
||||||
|
const selectElement = $("#parent_id");
|
||||||
|
let urlParents = selectElement.data("url");
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: "/warehouse/categories/parents", // create this route
|
url: urlParents,
|
||||||
type: "GET",
|
type: "GET",
|
||||||
success: function (data) {
|
success: function (data) {
|
||||||
$("#parent_id")
|
$("#parent_id")
|
||||||
|
|||||||
@@ -1,43 +1 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {});
|
||||||
const addBtn = document.getElementById("addDealerRow");
|
|
||||||
const dealerRows = document.getElementById("dynamicDealerRows");
|
|
||||||
|
|
||||||
// Get dealer data from Blade
|
|
||||||
const dealerDataDiv = document.getElementById("dealerData");
|
|
||||||
const dealers = JSON.parse(dealerDataDiv.getAttribute("data-dealers")); // 👈 this reads JSON from Blade
|
|
||||||
|
|
||||||
let rowCount = 0;
|
|
||||||
|
|
||||||
function createDealerRow(index) {
|
|
||||||
const dealerOptions = dealers
|
|
||||||
.map((d) => `<option value="${d.id}">${d.name}</option>`)
|
|
||||||
.join("");
|
|
||||||
return `
|
|
||||||
<div class="form-group row align-items-center dealer-row" data-index="${index}">
|
|
||||||
<div class="col-md-5">
|
|
||||||
<select name="dealer_stock[${index}][dealer_id]" class="form-control" required>
|
|
||||||
<option value="">-- Pilih Dealer --</option>
|
|
||||||
${dealerOptions}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<input type="number" name="dealer_stock[${index}][quantity]" class="form-control" value="1" min="1" required>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-3">
|
|
||||||
<button type="button" class="btn btn-danger btn-sm removeDealerRow">Hapus</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
addBtn.addEventListener("click", function () {
|
|
||||||
dealerRows.insertAdjacentHTML("beforeend", createDealerRow(rowCount));
|
|
||||||
rowCount++;
|
|
||||||
});
|
|
||||||
|
|
||||||
dealerRows.addEventListener("click", function (e) {
|
|
||||||
if (e.target.classList.contains("removeDealerRow")) {
|
|
||||||
e.target.closest(".dealer-row").remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,48 +1 @@
|
|||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {});
|
||||||
let dealerRowContainer = document.getElementById("dynamicDealerRows");
|
|
||||||
let addDealerButton = document.getElementById("addDealerRow");
|
|
||||||
|
|
||||||
// Initial index from existing dealer rows
|
|
||||||
let rowIndex =
|
|
||||||
dealerRowContainer.querySelectorAll(".dealer-stock-row").length;
|
|
||||||
|
|
||||||
addDealerButton.addEventListener("click", function () {
|
|
||||||
const newRow = document.createElement("div");
|
|
||||||
newRow.className = "form-group row align-items-center dealer-stock-row";
|
|
||||||
newRow.innerHTML = `
|
|
||||||
<div class="col-md-6">
|
|
||||||
<select name="dealer_stock[${rowIndex}][dealer_id]" class="form-control">
|
|
||||||
<option value="">-- Pilih Dealer --</option>
|
|
||||||
${generateDealerOptions()}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<input type="number" name="dealer_stock[${rowIndex}][quantity]" class="form-control" value="1" min="1" required placeholder="Jumlah Stok" />
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<button type="button" class="btn btn-danger btn-sm remove-dealer-row"> Hapus </button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
dealerRowContainer.appendChild(newRow);
|
|
||||||
rowIndex++;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle removal of dealer row
|
|
||||||
dealerRowContainer.addEventListener("click", function (event) {
|
|
||||||
if (
|
|
||||||
event.target &&
|
|
||||||
event.target.classList.contains("remove-dealer-row")
|
|
||||||
) {
|
|
||||||
event.target.closest(".dealer-stock-row").remove();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Function to generate dealer <option> elements dynamically
|
|
||||||
function generateDealerOptions() {
|
|
||||||
const dealerDataDiv = document.getElementById("dealerData");
|
|
||||||
const dealers = JSON.parse(dealerDataDiv.getAttribute("data-dealers"));
|
|
||||||
return dealers
|
|
||||||
.map((d) => `<option value="${d.id}">${d.name}</option>`)
|
|
||||||
.join("");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
$.ajaxSetup({
|
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
let tableContainer = $("#stock-mutations-table");
|
|
||||||
let url = tableContainer.data("url");
|
|
||||||
let table = $("#stock-mutations-table").DataTable({
|
|
||||||
processing: true,
|
|
||||||
serverSide: true,
|
|
||||||
ajax: url,
|
|
||||||
columns: [
|
|
||||||
{ data: "product_name", name: "product_name" },
|
|
||||||
{ data: "dealer_name", name: "dealer_name" },
|
|
||||||
{ data: "user_name", name: "user_name" },
|
|
||||||
{ data: "mutation_type_label", name: "mutation_type_label" },
|
|
||||||
{ data: "quantity", name: "quantity" },
|
|
||||||
{ data: "created_at", name: "created_at" },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
$.ajaxSetup({
|
|
||||||
headers: {
|
|
||||||
"X-CSRF-TOKEN": $('meta[name="csrf-token"]').attr("content"),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
let tableContainer = $("#stock-opnames-table");
|
|
||||||
let url = tableContainer.data("url");
|
|
||||||
let table = $("#stock-opnames-table").DataTable({
|
|
||||||
processing: true,
|
|
||||||
serverSide: true,
|
|
||||||
ajax: url,
|
|
||||||
columns: [
|
|
||||||
{ data: "product_name", name: "product_name" },
|
|
||||||
{ data: "dealer_name", name: "dealer_name" },
|
|
||||||
{ data: "user_name", name: "user_name" },
|
|
||||||
{ data: "system_quantity", name: "system_quantity" },
|
|
||||||
{ data: "physical_quantity", name: "physical_quantity" },
|
|
||||||
{ data: "difference", name: "difference" },
|
|
||||||
{ data: "opname_date", name: "opname_date" },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
@@ -138,18 +138,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Submenu Items --}}
|
{{-- Submenu Items --}}
|
||||||
@can('view', $menus['dealer.index'])
|
@can('view', $menus['user.index'])
|
||||||
<li class="kt-menu__item" aria-haspopup="true">
|
<li class="kt-menu__item" aria-haspopup="true">
|
||||||
<a href="{{ route('dealer.index') }}" class="kt-menu__link">
|
<a href="{{ route('user.index') }}" class="kt-menu__link">
|
||||||
<i class="fa fa-car" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
<i class="fa fa-car" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
||||||
<span class="kt-menu__link-text">Pengguna</span>
|
<span class="kt-menu__link-text">Pengguna</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@can('view', $menus['category.index'])
|
@can('view', $menus['roleprivileges.index'])
|
||||||
<li class="kt-menu__item" aria-haspopup="true">
|
<li class="kt-menu__item" aria-haspopup="true">
|
||||||
<a href="{{ route('category.index') }}" class="kt-menu__link">
|
<a href="{{ route('roleprivileges.index') }}" class="kt-menu__link">
|
||||||
<i class="fa fa-users" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
<i class="fa fa-users" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
||||||
<span class="kt-menu__link-text">Role & Privileges</span>
|
<span class="kt-menu__link-text">Role & Privileges</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -163,9 +163,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Submenu Items --}}
|
{{-- Submenu Items --}}
|
||||||
@can('view', $menus['dealer.index'])
|
@can('view', $menus['work.index'])
|
||||||
<li class="kt-menu__item" aria-haspopup="true">
|
<li class="kt-menu__item" aria-haspopup="true">
|
||||||
<a href="{{ route('dealer.index') }}" class="kt-menu__link">
|
<a href="{{ route('work.index') }}" class="kt-menu__link">
|
||||||
<i class="fa fa-car" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
<i class="fa fa-car" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
||||||
<span class="kt-menu__link-text">Pekerjaan</span>
|
<span class="kt-menu__link-text">Pekerjaan</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -181,9 +181,9 @@
|
|||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@can('view', $menus['work.index'])
|
@can('view', $menus['dealer.index'])
|
||||||
<li class="kt-menu__item" aria-haspopup="true">
|
<li class="kt-menu__item" aria-haspopup="true">
|
||||||
<a href="{{ route('work.index') }}" class="kt-menu__link">
|
<a href="{{ route('dealer.index') }}" class="kt-menu__link">
|
||||||
<i class="fa fa-list" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
<i class="fa fa-list" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
||||||
<span class="kt-menu__link-text">Dealer</span>
|
<span class="kt-menu__link-text">Dealer</span>
|
||||||
</a>
|
</a>
|
||||||
@@ -224,9 +224,9 @@
|
|||||||
</li>
|
</li>
|
||||||
@endcan
|
@endcan
|
||||||
|
|
||||||
@can('view', $menus['work.index'])
|
@can('view', $menus['opnames.index'])
|
||||||
<li class="kt-menu__item" aria-haspopup="true">
|
<li class="kt-menu__item" aria-haspopup="true">
|
||||||
<a href="{{ route('work.index') }}" class="kt-menu__link">
|
<a href="{{ route('opnames.index') }}" class="kt-menu__link">
|
||||||
<i class="fa fa-list" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
<i class="fa fa-list" style="display: flex; align-items: center; margin-right: 10px;"></i>
|
||||||
<span class="kt-menu__link-text">Stock Opname</span>
|
<span class="kt-menu__link-text">Stock Opname</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
<div class="kt-portlet__head-label">
|
<div class="kt-portlet__head-label">
|
||||||
<span class="kt-portlet__head-icon">
|
<span class="kt-portlet__head-icon">
|
||||||
<i class="kt-font-brand flaticon2-line-chart"></i>
|
<i class="kt-font-brand flaticon2-list-1"></i>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="kt-portlet__head-title">
|
<h3 class="kt-portlet__head-title">
|
||||||
Tabel Kategori Produk
|
Tabel Kategori Produk
|
||||||
@@ -58,7 +58,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="parent_id" class="form-label">Induk Kategori (Opsional)</label>
|
<label for="parent_id" class="form-label">Induk Kategori (Opsional)</label>
|
||||||
<select class="form-control" id="parent_id" name="parent_id">
|
<select class="form-control" id="parent_id" name="parent_id" data-url="{{ route('product_categories.parents') }}">
|
||||||
<option value="">-- Tidak ada (Kategori Utama) --</option>
|
<option value="">-- Tidak ada (Kategori Utama) --</option>
|
||||||
<!-- will be filled by JavaScript -->
|
<!-- will be filled by JavaScript -->
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
<div class="kt-portlet__head-label">
|
<div class="kt-portlet__head-label">
|
||||||
<span class="kt-portlet__head-icon">
|
<span class="kt-portlet__head-icon">
|
||||||
<i class="kt-font-brand flaticon2-line-chart"></i>
|
<i class="kt-font-brand flaticon2-plus"></i>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="kt-portlet__head-title">Tambah Produk</h3>
|
<h3 class="kt-portlet__head-title">Tambah Produk</h3>
|
||||||
</div>
|
</div>
|
||||||
@@ -59,18 +59,7 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Dynamic Dealer Stock Section --}}
|
|
||||||
<div id="dealerData" data-dealers='@json($dealers)'></div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label><strong>Stok per Dealer</strong></label>
|
|
||||||
<div id="dynamicDealerRows"></div>
|
|
||||||
|
|
||||||
<button type="button" id="addDealerRow" class="btn btn-outline-primary mt-2">
|
|
||||||
➕ Tambah Dealer
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Submit --}}
|
{{-- Submit --}}
|
||||||
<div class="form-group mt-4">
|
<div class="form-group mt-4">
|
||||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
<div class="kt-portlet__head-label">
|
<div class="kt-portlet__head-label">
|
||||||
<span class="kt-portlet__head-icon">
|
<span class="kt-portlet__head-icon">
|
||||||
<i class="kt-font-brand flaticon2-line-chart"></i>
|
<i class="kt-font-brand flaticon2-edit"></i>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="kt-portlet__head-title">Tambah Produk</h3>
|
<h3 class="kt-portlet__head-title">Ubah Produk</h3>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -32,6 +32,14 @@
|
|||||||
<input type="text" name="unit" id="unit" class="form-control" value="{{ old('unit', $product->unit) }}" required>
|
<input type="text" name="unit" id="unit" class="form-control" value="{{ old('unit', $product->unit) }}" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="active"><strong>Status Produk</strong></label>
|
||||||
|
<select name="active" class="form-control" required>
|
||||||
|
<option value="1">Aktif</option>
|
||||||
|
<option value="0">Tidak Aktif</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="description"><strong>Deskripsi</strong></label>
|
<label for="description"><strong>Deskripsi</strong></label>
|
||||||
<textarea name="description" id="description" class="form-control" rows="3">{{ old('description', $product->description) }}</textarea>
|
<textarea name="description" id="description" class="form-control" rows="3">{{ old('description', $product->description) }}</textarea>
|
||||||
@@ -55,36 +63,6 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Stok per Dealer --}}
|
|
||||||
<div id="dealerData" data-dealers='@json($dealers)'></div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label><strong>Stok per Dealer</strong></label>
|
|
||||||
<div id="dynamicDealerRows">
|
|
||||||
@foreach($product->dealers as $index => $dealer)
|
|
||||||
<div class="form-group row align-items-center dealer-stock-row">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<select name="dealer_stock[{{ $index }}][dealer_id]" class="form-control">
|
|
||||||
<option value="">-- Pilih Dealer --</option>
|
|
||||||
@foreach ($dealers as $d)
|
|
||||||
<option value="{{ $d->id }}" {{ $d->id == $dealer->id ? 'selected' : '' }}>
|
|
||||||
{{ $d->name }}
|
|
||||||
</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<input type="number" name="dealer_stock[{{ $index }}][quantity]" value="{{ $dealer->pivot->quantity }}" class="form-control" placeholder="Jumlah Stok" />
|
|
||||||
</div>
|
|
||||||
<div class="col-md-2">
|
|
||||||
<button type="button" class="btn btn-danger btn-sm remove-dealer-row">Hapus</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="button" id="addDealerRow" class="btn btn-outline-primary mt-2">➕ Tambah Dealer</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Submit --}}
|
{{-- Submit --}}
|
||||||
<div class="form-group mt-4">
|
<div class="form-group mt-4">
|
||||||
<button type="submit" class="btn btn-primary">Simpan</button>
|
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
<div class="kt-portlet__head-label">
|
<div class="kt-portlet__head-label">
|
||||||
<span class="kt-portlet__head-icon">
|
<span class="kt-portlet__head-icon">
|
||||||
<i class="kt-font-brand flaticon2-line-chart"></i>
|
<i class="kt-font-brand flaticon2-list-1"></i>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="kt-portlet__head-title">
|
<h3 class="kt-portlet__head-title">
|
||||||
Tabel Produk
|
Tabel Produk
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
<div class="kt-portlet__head-label">
|
<div class="kt-portlet__head-label">
|
||||||
<span class="kt-portlet__head-icon">
|
<span class="kt-portlet__head-icon">
|
||||||
<i class="kt-font-brand flaticon2-line-chart"></i>
|
<i class="kt-font-brand flaticon2-list-1"></i>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="kt-portlet__head-title">
|
<h3 class="kt-portlet__head-title">
|
||||||
Tabel Mutasi Stock Produk
|
Tabel Mutasi Stock Produk
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
@extends('layouts.backapp')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="kt-portlet kt-portlet--mobile" id="kt_blockui_datatable">
|
||||||
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
|
<div class="kt-portlet__head-label">
|
||||||
|
<span class="kt-portlet__head-icon">
|
||||||
|
<i class="kt-font-brand flaticon2-plus"></i>
|
||||||
|
</span>
|
||||||
|
<h3 class="kt-portlet__head-title">
|
||||||
|
Tambah Opname
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kt-portlet__body">
|
||||||
|
<form action="{{ route('opnames.store') }}" method="POST" id="opnameForm">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="product"><strong>Produk</strong></label>
|
||||||
|
<input type="text" class="form-control" name="product" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="dealer"><strong>Dealer</strong></label>
|
||||||
|
<input type="text" class="form-control" name="dealer" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="system_quantity"><strong>Total Sistem</strong></label>
|
||||||
|
<input type="number" class="form-control" name="system_quantity" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="phisycal_quantity"><strong>Total Sistem</strong></label>
|
||||||
|
<input type="number" class="form-control" name="phisycal_quantity" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="difference"><strong>Perbedaan</strong></label>
|
||||||
|
<input type="number" class="form-control" name="difference" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group mt-4">
|
||||||
|
<button type="submit" class="btn btn-primary">Simpan</button>
|
||||||
|
<a href="{{ route('opnames.index') }}" class="btn btn-secondary">Batal</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
||||||
|
@section('javascripts')
|
||||||
|
<script src="{{mix('js/warehouse_management/stock_opnames/create.js')}}"></script>
|
||||||
|
@endsection
|
||||||
@@ -5,13 +5,13 @@
|
|||||||
<div class="kt-portlet__head kt-portlet__head--lg">
|
<div class="kt-portlet__head kt-portlet__head--lg">
|
||||||
<div class="kt-portlet__head-label">
|
<div class="kt-portlet__head-label">
|
||||||
<span class="kt-portlet__head-icon">
|
<span class="kt-portlet__head-icon">
|
||||||
<i class="kt-font-brand flaticon2-line-chart"></i>
|
<i class="kt-font-brand flaticon2-list-1"></i>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="kt-portlet__head-title">
|
<h3 class="kt-portlet__head-title">
|
||||||
Tabel Mutasi Stock Produk
|
Tabel Stock Opname
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
@can('create', $menus['mutations.index'])
|
@can('create', $menus['opnames.index'])
|
||||||
<div class="kt-portlet__head-toolbar">
|
<div class="kt-portlet__head-toolbar">
|
||||||
<div class="kt-portlet__head-wrapper">
|
<div class="kt-portlet__head-wrapper">
|
||||||
<div class="kt-portlet__head-actions">
|
<div class="kt-portlet__head-actions">
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ use App\Http\Controllers\TransactionController;
|
|||||||
use App\Http\Controllers\UserController;
|
use App\Http\Controllers\UserController;
|
||||||
use App\Http\Controllers\WarehouseManagement\ProductCategoriesController;
|
use App\Http\Controllers\WarehouseManagement\ProductCategoriesController;
|
||||||
use App\Http\Controllers\WarehouseManagement\ProductsController;
|
use App\Http\Controllers\WarehouseManagement\ProductsController;
|
||||||
use App\Http\Controllers\WarehouseManagement\StockMutationsController;
|
|
||||||
use App\Http\Controllers\WarehouseManagement\StockOpnamesController;
|
|
||||||
use App\Http\Controllers\WorkController;
|
use App\Http\Controllers\WorkController;
|
||||||
use App\Models\Menu;
|
use App\Models\Menu;
|
||||||
use App\Models\Privilege;
|
use App\Models\Privilege;
|
||||||
@@ -205,13 +203,31 @@ Route::group(['middleware' => 'auth'], function() {
|
|||||||
Route::get('/report/transaction_dealer', [ReportController::class, 'transaction_dealer'])->name('report.transaction_dealer');
|
Route::get('/report/transaction_dealer', [ReportController::class, 'transaction_dealer'])->name('report.transaction_dealer');
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::prefix('warehouse')->group(function (){
|
Route::prefix('warehouse')->group(function () {
|
||||||
Route::resource('products', ProductsController::class);
|
|
||||||
Route::resource('product_categories', ProductCategoriesController::class);
|
// ProductsController routes
|
||||||
Route::get('categories/parents', [ProductCategoriesController::class, 'getParents'])->name('products.parents');
|
Route::prefix('products')->controller(ProductsController::class)->group(function () {
|
||||||
Route::post('products/{product}/toggle-active', [ProductsController::class, 'toggleActive'])->name('products.toggleActive');
|
Route::get('/', 'index')->name('products.index');
|
||||||
Route::get('mutations/index',[StockMutationsController::class, 'index'])->name('mutations.index');
|
Route::get('create', 'create')->name('products.create');
|
||||||
Route::get('opnames/index',[StockOpnamesController::class, 'index'])->name('opnames.index');
|
Route::post('/', 'store')->name('products.store');
|
||||||
|
Route::get('{product}', 'show')->name('products.show');
|
||||||
|
Route::get('{product}/edit', 'edit')->name('products.edit');
|
||||||
|
Route::put('{product}', 'update')->name('products.update');
|
||||||
|
Route::delete('{product}', 'destroy')->name('products.destroy');
|
||||||
|
Route::post('{product}/toggle-active', 'toggleActive')->name('products.toggleActive');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ProductCategoriesController routes
|
||||||
|
Route::prefix('product_categories')->controller(ProductCategoriesController::class)->group(function () {
|
||||||
|
Route::get('/', 'index')->name('product_categories.index');
|
||||||
|
Route::get('create', 'create')->name('product_categories.create');
|
||||||
|
Route::post('/', 'store')->name('product_categories.store');
|
||||||
|
Route::get('parents','product_category_parents')->name('product_categories.parents');
|
||||||
|
Route::get('{product_category}', 'show')->name('product_categories.show');
|
||||||
|
Route::get('{product_category}/edit', 'edit')->name('product_categories.edit');
|
||||||
|
Route::put('{product_category}', 'update')->name('product_categories.update');
|
||||||
|
Route::delete('{product_category}', 'destroy')->name('product_categories.destroy');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -29,14 +29,6 @@ mix.js("resources/js/app.js", "public/js")
|
|||||||
"resources/js/warehouse_management/products/edit.js",
|
"resources/js/warehouse_management/products/edit.js",
|
||||||
"public/js/warehouse_management/products"
|
"public/js/warehouse_management/products"
|
||||||
)
|
)
|
||||||
.js(
|
|
||||||
"resources/js/warehouse_management/stock_mutations/index.js",
|
|
||||||
"public/js/warehouse_management/stock_mutations"
|
|
||||||
)
|
|
||||||
.js(
|
|
||||||
"resources/js/warehouse_management/stock_opnames/index.js",
|
|
||||||
"public/js/warehouse_management/stock_opnames"
|
|
||||||
)
|
|
||||||
.sourceMaps();
|
.sourceMaps();
|
||||||
|
|
||||||
mix.browserSync({
|
mix.browserSync({
|
||||||
|
|||||||
Reference in New Issue
Block a user