Adjustments
This commit is contained in:
parent
9e649ea5b8
commit
64e9140db7
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('adjustments', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('branches_id')->after('id');
|
||||
$table->foreign('branches_id')->references('id')->on('branches')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('adjustments', function (Blueprint $table) {
|
||||
$table->dropForeign(['branches_id']);
|
||||
$table->dropColumn('branches_id');
|
||||
});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('adjusted_products', function (Blueprint $table) {
|
||||
$table->unsignedBigInteger('product_batch_id')->after('product_id');
|
||||
$table->foreign('product_batch_id')->references('id')->on('product_batches')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('adjusted_products', function (Blueprint $table) {
|
||||
$table->dropForeign(['product_batch_id']);
|
||||
$table->dropColumn('product_batch_id');
|
||||
});
|
||||
}
|
||||
};
|
|
@ -36,13 +36,14 @@ class AdjustmentController extends Controller
|
|||
'reference' => 'required|string|max:255',
|
||||
'date' => 'required|date',
|
||||
'note' => 'nullable|string|max:1000',
|
||||
'product_ids' => 'required',
|
||||
'product_batch_ids' => 'required',
|
||||
'quantities' => 'required',
|
||||
'types' => 'required'
|
||||
]);
|
||||
|
||||
DB::transaction(function () use ($request) {
|
||||
$adjustment = Adjustment::create([
|
||||
'branches_id' => session('branch_id'),
|
||||
'date' => $request->date,
|
||||
'note' => $request->note
|
||||
]);
|
||||
|
@ -51,22 +52,34 @@ class AdjustmentController extends Controller
|
|||
AdjustedProduct::create([
|
||||
'adjustment_id' => $adjustment->id,
|
||||
'product_id' => $id,
|
||||
'product_batch_id' => $request->product_batch_ids[$key],
|
||||
'quantity' => $request->quantities[$key],
|
||||
'type' => $request->types[$key]
|
||||
]);
|
||||
|
||||
$product = Product::findOrFail($id);
|
||||
$batchId = $request->product_batch_ids[$key]; // batch yang dipilih oleh user
|
||||
$batch = DB::table('product_batches')->where('id', $batchId)->lockForUpdate()->first();
|
||||
|
||||
if ($batch) {
|
||||
if ($request->types[$key] == 'add') {
|
||||
$product->update([
|
||||
'product_quantity' => $product->product_quantity + $request->quantities[$key]
|
||||
DB::table('product_batches')->where('id', $batchId)->update([
|
||||
'qty' => $batch->qty + $request->quantities[$key]
|
||||
]);
|
||||
} elseif ($request->types[$key] == 'sub') {
|
||||
$product->update([
|
||||
'product_quantity' => $product->product_quantity - $request->quantities[$key]
|
||||
$newQty = $batch->qty - $request->quantities[$key];
|
||||
if ($newQty < 0) {
|
||||
throw new \Exception("Stock untuk batch {$batch->batch_code} tidak mencukupi.");
|
||||
}
|
||||
|
||||
DB::table('product_batches')->where('id', $batchId)->update([
|
||||
'qty' => $newQty
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
throw new \Exception("Batch tidak ditemukan.");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
toast('Adjustment Created!', 'success');
|
||||
|
@ -128,6 +141,7 @@ class AdjustmentController extends Controller
|
|||
AdjustedProduct::create([
|
||||
'adjustment_id' => $adjustment->id,
|
||||
'product_id' => $id,
|
||||
'product_batch_id' => $request->batch_ids[$key],
|
||||
'quantity' => $request->quantities[$key],
|
||||
'type' => $request->types[$key]
|
||||
]);
|
||||
|
|
|
@ -30,24 +30,26 @@ class ProductTable extends Component
|
|||
}
|
||||
|
||||
public function productSelected($product) {
|
||||
switch ($this->hasAdjustments) {
|
||||
case true:
|
||||
if (in_array($product, array_map(function ($adjustment) {
|
||||
return $adjustment['product'];
|
||||
}, $this->products))) {
|
||||
return session()->flash('message', 'Already exists in the product list!');
|
||||
}
|
||||
break;
|
||||
case false:
|
||||
if (in_array($product, $this->products)) {
|
||||
return session()->flash('message', 'Already exists in the product list!');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return session()->flash('message', 'Something went wrong!');
|
||||
$branch_id = session('branch_id'); // pastikan session branch_id sudah ada
|
||||
$productModel = Product::with(['batches' => function($q) use ($branch_id) {
|
||||
$q->where('branch_id', $branch_id)->where('qty', '>', 0);
|
||||
}])->find($product['id']);
|
||||
|
||||
if (!$productModel) {
|
||||
return session()->flash('message', 'Produk tidak ditemukan!');
|
||||
}
|
||||
|
||||
array_push($this->products, $product);
|
||||
// Cek duplikasi
|
||||
foreach ($this->products as $p) {
|
||||
if ($p['id'] == $productModel->id) {
|
||||
return session()->flash('message', 'Already exists in the product list!');
|
||||
}
|
||||
}
|
||||
|
||||
$productArr = $productModel->toArray();
|
||||
$productArr['batches'] = $productModel->batches->toArray();
|
||||
|
||||
$this->products[] = $productArr;
|
||||
}
|
||||
|
||||
public function removeProduct($key) {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<div>
|
||||
{{-- Alert Message --}}
|
||||
@if (session()->has('message'))
|
||||
<div class="alert alert-warning alert-dismissible fade show" role="alert">
|
||||
<div class="alert-body">
|
||||
|
@ -9,60 +10,86 @@
|
|||
</div>
|
||||
</div>
|
||||
@endif
|
||||
<div class="table-responsive">
|
||||
<div wire:loading.flex class="col-12 position-absolute justify-content-center align-items-center" style="top:0;right:0;left:0;bottom:0;background-color: rgba(255,255,255,0.5);z-index: 99;">
|
||||
|
||||
{{-- Loading Overlay --}}
|
||||
<div wire:loading.flex class="col-12 position-absolute justify-content-center align-items-center"
|
||||
style="top:0;right:0;left:0;bottom:0;background-color: rgba(255,255,255,0.5);z-index: 99;">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Product Table --}}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr class="align-middle">
|
||||
<th class="align-middle">#</th>
|
||||
<th class="align-middle">Product Name</th>
|
||||
<th class="align-middle">Code</th>
|
||||
<th class="align-middle">Stock</th>
|
||||
<th class="align-middle">Quantity</th>
|
||||
<th class="align-middle">Type</th>
|
||||
<th class="align-middle">Action</th>
|
||||
<tr class="align-middle text-center">
|
||||
<th>#</th>
|
||||
<th>Product Name</th>
|
||||
<th>Code</th>
|
||||
<th>Batch</th>
|
||||
<th>Stock</th>
|
||||
<th>Quantity</th>
|
||||
<th>Type</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@if(!empty($products))
|
||||
@foreach($products as $key => $product)
|
||||
@if (!empty($products))
|
||||
@foreach ($products as $key => $product)
|
||||
@php
|
||||
$productData = $product['product'] ?? $product;
|
||||
$batches = $product['batches'] ?? [];
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="align-middle">{{ $key + 1 }}</td>
|
||||
<td class="align-middle">{{ $product['product_name'] ?? $product['product']['product_name'] }}</td>
|
||||
<td class="align-middle">{{ $product['product_code'] ?? $product['product']['product_code'] }}</td>
|
||||
<td class="align-middle text-center">{{ $key + 1 }}</td>
|
||||
|
||||
{{-- Product Name --}}
|
||||
<td class="align-middle">{{ $productData['product_name'] }}</td>
|
||||
|
||||
{{-- Product Code --}}
|
||||
<td class="align-middle">{{ $productData['product_code'] }}</td>
|
||||
|
||||
{{-- Batch Select --}}
|
||||
<td class="align-middle">
|
||||
<select name="product_batch_ids[]" class="form-control" required>
|
||||
<option value="">Pilih Batch</option>
|
||||
@foreach ($batches as $batch)
|
||||
<option value="{{ $batch['id'] }}">
|
||||
{{ $batch['batch_code'] ?? '-' }} | Qty: {{ $batch['qty'] }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
|
||||
{{-- Stock (dari batch, default ambil batch pertama jika ada) --}}
|
||||
<td class="align-middle text-center">
|
||||
@php
|
||||
$firstBatch = $batches[0] ?? null;
|
||||
@endphp
|
||||
<span class="badge badge-info">
|
||||
{{ $product['product_quantity'] ?? $product['product']['product_quantity'] }} {{ $product['product_unit'] ?? $product['product']['product_unit'] }}
|
||||
{{ $firstBatch['qty'] ?? '0' }} {{ $productData['product_unit'] }}
|
||||
</span>
|
||||
</td>
|
||||
<input type="hidden" name="product_ids[]" value="{{ $product['product']['id'] ?? $product['id'] }}">
|
||||
|
||||
{{-- Quantity Input --}}
|
||||
<td class="align-middle">
|
||||
<input type="number" name="quantities[]" min="1" class="form-control" value="{{ $product['quantity'] ?? 1 }}">
|
||||
<input type="number" name="quantities[]" min="1" class="form-control"
|
||||
value="{{ $product['quantity'] ?? 1 }}">
|
||||
</td>
|
||||
|
||||
{{-- Type Select --}}
|
||||
<td class="align-middle">
|
||||
@if(isset($product['type']))
|
||||
@if($product['type'] == 'add')
|
||||
<select name="types[]" class="form-control">
|
||||
<option value="add" selected>(+) Addition</option>
|
||||
<option value="sub">(-) Subtraction</option>
|
||||
<option value="add" {{ ($product['type'] ?? '') === 'add' ? 'selected' : '' }}>(+) Addition</option>
|
||||
<option value="sub" {{ ($product['type'] ?? '') === 'sub' ? 'selected' : '' }}>(-) Subtraction</option>
|
||||
</select>
|
||||
@elseif($product['type'] == 'sub')
|
||||
<select name="types[]" class="form-control">
|
||||
<option value="sub" selected>(-) Subtraction</option>
|
||||
<option value="add">(+) Addition</option>
|
||||
</select>
|
||||
@endif
|
||||
@else
|
||||
<select name="types[]" class="form-control">
|
||||
<option value="add">(+) Addition</option>
|
||||
<option value="sub">(-) Subtraction</option>
|
||||
</select>
|
||||
@endif
|
||||
</td>
|
||||
|
||||
{{-- Hidden Product ID --}}
|
||||
<input type="hidden" name="product_ids[]" value="{{ $productData['id'] }}">
|
||||
|
||||
{{-- Action Button --}}
|
||||
<td class="align-middle text-center">
|
||||
<button type="button" class="btn btn-danger" wire:click="removeProduct({{ $key }})">
|
||||
<i class="bi bi-trash"></i>
|
||||
|
@ -72,10 +99,8 @@
|
|||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">
|
||||
<span class="text-danger">
|
||||
Please search & select products!
|
||||
</span>
|
||||
<td colspan="8" class="text-center">
|
||||
<span class="text-danger">Please search & select products!</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
|
|
Loading…
Reference in New Issue