salesentry filters

This commit is contained in:
Sampanna Rimal 2024-09-17 16:34:40 +05:45
parent afb2c202d6
commit 0b438e302d
19 changed files with 303 additions and 50 deletions

View File

@ -148,4 +148,17 @@ class ProductController extends Controller
'data' => $productModel, 'data' => $productModel,
]); ]);
} }
public function getProductsByCategory(Request $request)
{
$categoryId = $request->category_id;
try {
$products = $this->productRepository->getProductsByCategory($categoryId);
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return response()->json(['products' => $products]);
}
} }

View File

@ -7,6 +7,7 @@ interface ProductInterface
public function findAll(); public function findAll();
public function getProductById($ProductId); public function getProductById($ProductId);
public function getProductByEmail($email); public function getProductByEmail($email);
public function getProductsByCategory($categoryId);
public function delete($ProductId); public function delete($ProductId);
public function create($ProductDetails); public function create($ProductDetails);
public function update($ProductId, array $newDetails); public function update($ProductId, array $newDetails);

View File

@ -23,6 +23,11 @@ class ProductRepository implements ProductInterface
return Product::where('email', $email)->first(); return Product::where('email', $email)->first();
} }
public function getProductsByCategory($categoryId)
{
return Product::where('category_id', $categoryId)->pluck('name', 'id');
}
public function delete($ProductId) public function delete($ProductId)
{ {
Product::destroy($ProductId); Product::destroy($ProductId);

View File

@ -25,12 +25,12 @@
<div class="col-md-12"> <div class="col-md-12">
{{ html()->label('Description')->class('form-label') }} {{ html()->label('Description')->class('form-label') }}
{{ html()->textarea('desc')->class('form-control')->placeholder('Enter Description')->required() }} {{ html()->textarea('desc')->class('form-control')->placeholder('Enter Description') }}
</div> </div>
<div class="col-md-12"> <div class="col-md-12">
{{ html()->label('Remarks')->class('form-label') }} {{ html()->label('Remarks')->class('form-label') }}
{{ html()->textarea('remarks')->class('form-control')->placeholder('Enter Remarks')->required() }} {{ html()->textarea('remarks')->class('form-control')->placeholder('Enter Remarks') }}
</div> </div>
</div> </div>

View File

@ -26,6 +26,6 @@ Route::group([], function () {
Route::resource('fabricCategory', FabricCategoryController::class)->names('fabricCategory'); Route::resource('fabricCategory', FabricCategoryController::class)->names('fabricCategory');
Route::get('get-sub-categories', [SubCategoryController::class, 'getSubCategories'])->name('getSubCategories'); Route::get('get-sub-categories', [SubCategoryController::class, 'getSubCategories'])->name('getSubCategories');
Route::get('product-details', [ProductController::class, 'getProductDetail'])->name('get-product-detail'); Route::get('product-details', [ProductController::class, 'getProductDetail'])->name('get-product-detail');
Route::get('/products-by-category', [ProductController::class, 'getProductsByCategory'])->name('products-by-category');
}); });

View File

@ -42,10 +42,14 @@ class SalesEntryController extends Controller
/** /**
* Display a listing of the resource. * Display a listing of the resource.
*/ */
public function index() public function index(Request $request)
{ {
$filters = $request->all();
$data['title'] = 'Sales Entries'; $data['title'] = 'Sales Entries';
$data['salesEntries'] = SalesEntry::all(); $data['stockList'] = $this->stockRepository->pluck();
$data['productList'] = $this->productRepository->pluck();
$data['categoryList'] = $this->categoryRepository->pluck();
$data['salesEntries'] = $this->salesEntryRepository->findAll($filters);
return view('salesEntry::salesEntry.index', $data); return view('salesEntry::salesEntry.index', $data);
} }
@ -55,9 +59,9 @@ class SalesEntryController extends Controller
public function create() public function create()
{ {
$data['title'] = 'New Sales Entry'; $data['title'] = 'New Sales Entry';
$data['categoryList'] = $this->categoryRepository->pluck();
$data['stockList'] = $this->stockRepository->pluck(); $data['stockList'] = $this->stockRepository->pluck();
$data['productList'] = $this->productRepository->pluck(); $data['productList'] = $this->productRepository->pluck();
$data['categoryList'] = $this->categoryRepository->pluck();
$data['customerList'] = $this->customerRepository->pluck(); $data['customerList'] = $this->customerRepository->pluck();
$data['sizes'] = $this->fieldRepository->getDropdownByAlias('size'); $data['sizes'] = $this->fieldRepository->getDropdownByAlias('size');
$data['paymentModes'] = $this->fieldRepository->getDropdownByAlias('payment-mode'); $data['paymentModes'] = $this->fieldRepository->getDropdownByAlias('payment-mode');
@ -127,9 +131,11 @@ class SalesEntryController extends Controller
$productList= $this->productRepository->pluck('id'); $productList= $this->productRepository->pluck('id');
$stockList= $this->stockRepository->pluck('id'); $stockList= $this->stockRepository->pluck('id');
$categoryList= $this->categoryRepository->pluck('id'); $categoryList= $this->categoryRepository->pluck('id');
$sizes = $this->fieldRepository->getDropdownByAlias('size');
$paymentModes = $this->fieldRepository->getDropdownByAlias('payment-mode');
return response()->json([ return response()->json([
'view' => view('salesEntry::salesEntry.clone-product', compact('data', 'numInc', 'script', 'productList'))->render(), 'view' => view('salesEntry::salesEntry.clone-product', compact('data', 'numInc', 'script', 'productList', 'categoryList', 'stockList', 'sizes', 'paymentModes'))->render(),
]); ]);
} }
} }

View File

@ -15,7 +15,16 @@ class SalesEntry extends Model
USE StatusTrait; USE StatusTrait;
protected $table = 'tbl_salesentries'; protected $table = 'tbl_salesentries';
protected $guarded = []; protected $fillable = [
'customer_id',
'sales_date',
'payment',
'paymentmode_id',
'paymentref',
'total_amt',
'created_at',
'updated_at'
];
protected $appends = ['status_name']; protected $appends = ['status_name'];

View File

@ -14,7 +14,20 @@ class SalesEntryDetail extends Model
USE StatusTrait; USE StatusTrait;
protected $table = 'tbl_salesentrydetails'; protected $table = 'tbl_salesentrydetails';
protected $guarded = []; protected $fillable = [
'salesentry_id',
'product_id',
'category_id',
'stock_id',
'size_id',
'unit',
'rate',
'quantity',
'amount',
'desc',
'created_at',
'updated_at'
];
protected $appends = ['status_name']; protected $appends = ['status_name'];

View File

@ -6,7 +6,7 @@ use Illuminate\Http\Request;
interface SalesEntryInterface interface SalesEntryInterface
{ {
public function findAll(); public function findAll($filters);
public function getSalesEntryById($SalesEntryId); public function getSalesEntryById($SalesEntryId);
public function getSalesEntryByEmail($email); public function getSalesEntryByEmail($email);
public function delete($SalesEntryId); public function delete($SalesEntryId);

View File

@ -9,10 +9,37 @@ use Illuminate\Support\Facades\DB;
class SalesEntryRepository implements SalesEntryInterface class SalesEntryRepository implements SalesEntryInterface
{ {
public function findAll() // public function findAll()
// {
// return SalesEntry::when(true, function ($query) {
// })->paginate(20);
// }
public function findAll($filters = [], $limit = null, $offset = null)
{ {
return SalesEntry::when(true, function ($query) { return SalesEntry::when($filters, function ($query) use ($filters) {
})->paginate(20);
if (isset($filters["category_id"])) {
$query->whereHas('salesEntryDetails', function ( $query) use ($filters) {
$query->where('category_id', '=', $filters["category_id"]);
});
}
if (isset($filters["product_id"])) {
$query->whereHas('salesEntryDetails', function ( $query) use ($filters) {
$query->where('product_id', '=', $filters["product_id"]);
});
}
if (isset($filters["stock_id"])) {
$query->whereHas('salesEntryDetails', function ( $query) use ($filters) {
$query->where('stock_id', '=', $filters["stock_id"]);
});
}
if (isset($filters["date"])) {
$explodeDate = explode("to", $filters['date']);
$query->whereBetween("sales_date", [$explodeDate[0], preg_replace('/\s+/', '', $explodeDate[1])]);
}
})->get();
} }
public function getSalesEntryById($SalesEntryId) public function getSalesEntryById($SalesEntryId)
@ -44,12 +71,16 @@ class SalesEntryRepository implements SalesEntryInterface
$request->merge(['salesentry_id' => $salesEntryData->id]); $request->merge(['salesentry_id' => $salesEntryData->id]);
foreach ($salesEntryDetails['product_id'] as $key => $productId) { foreach ($salesEntryDetails['stock_id'] as $key => $stockId) {
// dd($request->input('salesentry_id'));
$data = [ $data = [
'salesentry_id' => $request->input('salesentry_id'), 'salesentry_id' => $request->input('salesentry_id'),
'product_id' => $productId, 'product_id' => $salesEntryDetails['product_id'][$key],
'unit' => $salesEntryDetails['unit'][$key], 'category_id' => $salesEntryDetails['category_id'][$key],
'stock_id' => $salesEntryDetails['stock_id'][$key],
'size_id' => $salesEntryDetails['size_id'][$key],
'rate' => $salesEntryDetails['rate'][$key], 'rate' => $salesEntryDetails['rate'][$key],
// 'unit' => $salesEntryDetails['unit'][$key],
'quantity' => $salesEntryDetails['qty'][$key], 'quantity' => $salesEntryDetails['qty'][$key],
'amount' => $salesEntryDetails['amt'][$key], 'amount' => $salesEntryDetails['amt'][$key],
'desc' => $salesEntryDetails['desc'][$key], 'desc' => $salesEntryDetails['desc'][$key],

View File

@ -15,20 +15,11 @@ return new class extends Migration
{ {
Schema::create('tbl_salesentries', function (Blueprint $table) { Schema::create('tbl_salesentries', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('title')->nullable();
$table->string('slug')->nullable();
$table->date('sales_date')->nullable(); $table->date('sales_date')->nullable();
$table->unsignedBigInteger('customer_id')->nullable(); $table->unsignedBigInteger('customer_id')->nullable();
$table->unsignedBigInteger('product_id')->nullable();
$table->unsignedBigInteger('category_id')->nullable();
$table->unsignedBigInteger('stock_id')->nullable();
$table->unsignedBigInteger('size_id')->nullable();
$table->string('payment')->nullable(); $table->string('payment')->nullable();
$table->unsignedBigInteger('paymentmode_id')->nullable(); $table->unsignedBigInteger('paymentmode_id')->nullable();
$table->string('paymentref')->nullable(); $table->string('paymentref')->nullable();
$table->decimal('sub_total', 10, 2)->nullable();
$table->decimal('tax', 10, 2)->nullable();
$table->decimal('discount_amt', 10, 2)->nullable();
$table->decimal('total_amt', 10, 2)->nullable(); $table->decimal('total_amt', 10, 2)->nullable();
$table->timestamps(); $table->timestamps();
}); });

View File

@ -1,30 +1,45 @@
<div class="card card-body product-card card-border-secondary mb-2 border"> <div class="card card-body product-card card-border-secondary mb-2 border">
<div class="row gy-2 mb-2"> <div class="row gy-2 mb-2">
<div class="col-md-4"> <div class="col-md-2">
{{ html()->label('Category')->class('form-label') }}
@if (isset($editable) && $editable)
{{ html()->select('category_id[]', $categoryList, $item->category_id)->class('form-select category_id')->attributes(['id' => 'category_id'])->placeholder('Enter Category')->required() }}
@else
{{ html()->select('category_id[]', $categoryList)->class('form-select category_id')->attributes(['id' => 'category_id'])->placeholder('Enter Category')->required() }}
@endif
</div>
<div class="col-md-3">
{{ html()->label('Product')->class('form-label') }} {{ html()->label('Product')->class('form-label') }}
@if (isset($editable) && $editable) @if (isset($editable) && $editable)
{{ html()->select('product_id[]', $productList, $item->product_id)->class('form-select product_id')->attributes(['id' => 'product_id'])->placeholder('Enter Product Name')->required() }} {{ html()->select('product_id[]', $productList, $item->product_id)->class('form-select product_id')->attributes(['id' => 'product_id'])->placeholder('')->required() }}
@else @else
{{ html()->select('product_id[]', [], null)->class('form-select product_id')->attributes(['id' => 'product_id'])->placeholder('')->required()->disabled() }}
@endif @endif
{{ html()->select('product_id[]', $productList)->class('form-select product_id')->attributes(['id' => 'product_id'])->placeholder('Enter Product Name')->required() }} </div>
<div class="col-md-2">
{{ html()->label('Stock')->class('form-label') }}
@if (isset($editable) && $editable)
{{ html()->select('stock_id[]', $stockList, $item->stock_id)->class('form-select stock_id')->attributes(['id' => 'stock_id'])->placeholder('')->required() }}
@else
{{ html()->select('stock_id[]', $stockList)->class('form-select stock_id')->attributes(['id' => 'stock_id'])->placeholder('')->required()->disabled() }}
@endif
</div>
<div class="col-md-1">
{{ html()->label('Size')->class('form-label') }}
{{ html()->select('size_id[]', $sizes)->class('form-select ')->placeholder('size') }}
</div> </div>
<div class="col-md-2"> <div class="col-md-1">
{{ html()->label('Unit')->class('form-label') }}
{{ html()->text('unit[]', isset($editable) && $editable ? $item->unit : null)->class('form-control unit')->placeholder('Enter Unit')->required()->attributes(['id' => 'unit']) }}
</div>
<div class="col-md-2">
{{ html()->label('Rate')->class('form-label') }} {{ html()->label('Rate')->class('form-label') }}
{{ html()->text('rate[]', isset($editable) && $editable ? $item->rate : null)->class('form-control product-price cleave-numeral rate~~')->placeholder('Enter Rate')->attributes(['id' => 'rate']) }} {{ html()->text('rate[]', isset($editable) && $editable ? $item->rate : null)->class('form-control product-price cleave-numeral rate~~')->placeholder('Enter Rate')->attributes(['id' => 'rate', 'onkeyup' => 'validateNumericInput(this)']) }}
</div> </div>
<div class="col-md-2"> <div class="col-md-1">
{{ html()->label('Quantity')->class('form-label') }} {{ html()->label('Quantity')->class('form-label') }}
{{ html()->text('qty[]', isset($editable) && $editable ? $item->quantity : null)->class('form-control product-quantity cleave-numeral qty')->placeholder('Enter QTY')->attributes(['id' => 'qty']) }} {{ html()->text('qty[]', isset($editable) && $editable ? $item->quantity : null)->class('form-control product-quantity cleave-numeral qty')->placeholder('Enter QTY')->attributes(['id' => 'qty', 'onkeyup' => 'validateNumericInput(this)']) }}
</div> </div>
<div class="col-md-2"> <div class="col-md-2">

View File

@ -1,8 +1,9 @@
@extends('layouts.app') @extends('layouts.app')
@section('content') @section('content')
<div class="page-content"> <div class="page-content">
<div class="container-fluid"> <div class="container-fluid">
@include('salesEntry::salesEntry.partials.menu')
<div class="row"> <div class="row">
<div class="col-lg-12"> <div class="col-lg-12">
<div class="card"> <div class="card">
@ -24,20 +25,22 @@
<th>Customer</th> <th>Customer</th>
<th>Sales Date</th> <th>Sales Date</th>
<th>Total Amount</th> <th>Total Amount</th>
<th>Action</th> {{-- <th>Action</th> --}}
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@forelse ($salesEntries as $key => $item) @forelse ($salesEntries as $key => $item)
{{-- @dd($item) --}}
<tr> <tr>
<td>{{ $key + 1 }}</td> <td>{{ $key + 1 }}</td>
<td>{{ $item->customer->customer_name }}</td> <td>{{ $item->customer->customer_name }}</td>
<td>{{ $item->sales_date }}</td> <td>{{ $item->sales_date }}</td>
<td>{{ $item->total_amt }}</td> <td>{{ $item->total_amt }}</td>
<td> {{-- <td>
<div class="hstack flex-wrap gap-3"> <div class="hstack flex-wrap gap-3">
<a href="javascript:void(0);" class="link-info fs-15 view-item-btn" <a href="javascript:void(0);" class="link-info fs-15 view-item-btn"
data-bs-toggle="modal" data-bs-target="#viewModal"> data-bs-toggle="modal" data-bs-target="#viewModal" data-link="{{ route('salesEntry.show', $item->id) }}">
<i class="ri-eye-line"></i> <i class="ri-eye-line"></i>
</a> </a>
<a href="{{ route('salesEntry.edit', $item->id) }}" <a href="{{ route('salesEntry.edit', $item->id) }}"
@ -51,7 +54,7 @@
class="ri-delete-bin-line"></i></a> class="ri-delete-bin-line"></i></a>
</div> </div>
</td> </td> --}}
</tr> </tr>
@empty @empty
@endforelse @endforelse

View File

@ -80,7 +80,7 @@
</div> </div>
<div class="row gy-1 my-2"> <div class="row gy-1 my-2 mb-4">
<h5 class="text-primary text-center">Payment Details</h5> <h5 class="text-primary text-center">Payment Details</h5>
<div class="border border-dashed"></div> <div class="border border-dashed"></div>
@ -102,7 +102,7 @@
</div> </div>
<div class="mb-4 text-end"> <div class="mb-4 mt-4 text-end">
<button type="submit" class="btn btn-success w-sm">Save</button> <button type="submit" class="btn btn-success w-sm">Save</button>
</div> </div>
@ -117,12 +117,11 @@
numberInc = $('.product-card').length numberInc = $('.product-card').length
$.ajax({ $.ajax({
type: 'get', type: 'get',
url: '{{ url('clone-sales-product') }}', url: '{{ route('salesEntry.cloneSalesProduct') }}',
data: { data: {
numberInc: numberInc numberInc: numberInc
}, },
success: function(response) { success: function(response) {
$('.appendProductCard').append(response.view) $('.appendProductCard').append(response.view)
// $('#salesEntry-container').html(response.view).fadeIn() // $('#salesEntry-container').html(response.view).fadeIn()
}, },
@ -143,6 +142,11 @@
recalculate(); recalculate();
}) })
function validateNumericInput(input) {
// Allow only numbers and remove any non-numeric input
input.value = input.value.replace(/[^0-9]/g, '');
}
function amountKeyup() { function amountKeyup() {
$("body").on('keyup', '.product-price', function() { $("body").on('keyup', '.product-price', function() {
@ -187,8 +191,10 @@
// $("#shipping").val(shipping.toFixed(2)); // $("#shipping").val(shipping.toFixed(2));
$("#total").val(subtotal.toFixed(2)); $("#total").val(subtotal.toFixed(2));
} }
$(document).ready(function() { $(document).ready(function() {
$('.product_id').prop('disabled', true);
$('.stock_id').prop('disabled', true);
$('body').on('change', '.product_id', function() { $('body').on('change', '.product_id', function() {
var selectedId = $(this).find(':selected').val(); var selectedId = $(this).find(':selected').val();
var formRow = $(this).closest('.row'); var formRow = $(this).closest('.row');
@ -214,6 +220,72 @@
}); });
} }
}); });
// When category is selected, load products dynamically
$('body').on('change', '.category_id', function () {
var categoryId = $(this).val();
var formRow = $(this).closest('.row');
var productSelect = formRow.find('.product_id');
var stockSelect = formRow.find('.stock_id');
// Reset stock field
if (categoryId) {
$.ajax({
type: 'GET',
url: '{{ route('products-by-category') }}', // Route to get products by category
data: {category_id:categoryId},
success: function (response) {
productSelect.empty().append('<option value="">Select Product</option>');
productSelect.prop('disabled', false);
$.each(response.products, function (id, name) {
productSelect.append('<option value="' + id + '">' + name + '</option>');
});
},
error: function (xhr) {
// Handle error
}
});
stockSelect.empty().prop('disabled', true);
} else {
productSelect.prop('disabled', true);
}
});
// When product is selected, load stocks dynamically
$('body').on('change', '.product_id', function () {
var productId = $(this).val();
var formRow = $(this).closest('.row');
var productSelect = formRow.find('.product_id');
var stockSelect = formRow.find('.stock_id');
if (productId) {
$.ajax({
type: 'GET',
url: '{{ route('stocks-by-product') }}', // Route to get stocks by product
data: {product_id:productId},
success: function (response) {
stockSelect.empty().append('<option value="">Select Stock</option>');
stockSelect.prop('disabled', false);
$.each(response.stocks, function (id, title) {
stockSelect.append('<option value="' + id + '">' + title + '</option>');
});
},
error: function (xhr) {
// Handle error
}
});
} else {
stockSelect.prop('disabled', true);
}
});
}); });
</script> </script>
@endpush @endpush

View File

@ -0,0 +1,74 @@
<div class="card">
<div class="card-body">
<div class="row g-2">
<div class="col-sm-12">
{{ html()->form('GET')->route('salesEntry.index')->open() }}
<div class="row g-8">
{{-- <div class="col-xl-3">
<div class="search-box">
{{ html()->text('search')->class('form-control search')->value(request('search'))->placeholder('Search...') }}
<i class="ri-search-line search-icon"></i>
</div>
</div> --}}
<div class="col-sm-3">
<div class="">
{{ html()->text('date')->class('form-control')->value(request('date'))->placeholder('Date Range')->attributes([
'id' => 'datepicker-range',
'data-provider' => 'flatpickr',
'data-date-format' => 'Y-m-d',
'data-range-date' => 'true',
]) }}
</div>
</div>
<div class="col-sm-2">
<div class="search-box">
{{ html()->select('category_id', $categoryList)->class('form-control select2')->value(request('category_id'))->placeholder('By Category') }}
</div>
</div>
<div class="col-sm-2">
<div class="search-box">
{{ html()->select('stock_id', $stockList)->class('form-control select2')->value(request('stock_id'))->placeholder('By Stock') }}
</div>
</div>
<div class="col-sm-2">
<div class="search-box">
{{ html()->select('product_id', $productList)->class('form-control select2')->value(request('product_id'))->placeholder('By Product') }}
</div>
</div>
<!--end col-->
{{-- <div class="align-item-right"> --}}
<div class="col-sm-1 offset-lg-1">
<div>
<button type="submit" class="btn btn-primary">
<i class="ri-equalizer-fill me-2"></i>Filters</button>
{{-- <a href="{{ route('task.index') }}" class="btn btn-danger">
<i class="ri-bin-fill me-2"></i>Reset</a> --}}
</div>
</div>
<div class="col-sm-1">
<div>
<a href="{{ route('salesEntry.index') }}" class="btn btn-primary">
<i class="ri-loop-right-line me-2"></i>Reset</a>
{{-- <a href="{{ route('task.index') }}" class="btn btn-danger">
<i class="ri-bin-fill me-2"></i>Reset</a> --}}
</div>
</div>
{{-- </div> --}}
<!--end col-->
</div>
<!--end row-->
{{ html()->form()->close() }}
</div>
<!--end col-->
</div>
<!--end row-->
</div>
</div>
<script>
</script>

View File

@ -94,4 +94,16 @@ class StockController extends Controller
return response()->json(['status' => true, 'message' => 'Stock Deleted Successfully']); return response()->json(['status' => true, 'message' => 'Stock Deleted Successfully']);
} }
public function getStocksByProduct(Request $request)
{
$productId = $request->product_id;
try {
$stocks = $this->stockRepository->getStocksByProduct($productId);
} catch (\Throwable $th) {
toastr()->error($th->getMessage());
}
return response()->json(['stocks' => $stocks]);
}
} }

View File

@ -7,6 +7,7 @@ interface StockInterface
public function findAll(); public function findAll();
public function getStockById($StockId); public function getStockById($StockId);
public function getStockByEmail($email); public function getStockByEmail($email);
public function getStocksByProduct($productId);
public function delete($StockId); public function delete($StockId);
public function create($StockDetails); public function create($StockDetails);
public function update($StockId, array $newDetails); public function update($StockId, array $newDetails);

View File

@ -23,6 +23,11 @@ class StockRepository implements StockInterface
return Stock::where('email', $email)->first(); return Stock::where('email', $email)->first();
} }
public function getStocksByProduct($productId)
{
return Stock::where('product_id', $productId)->pluck('title', 'id');
}
public function delete($StockId) public function delete($StockId)
{ {
Stock::destroy($StockId); Stock::destroy($StockId);

View File

@ -19,5 +19,7 @@ use Modules\Stock\Http\Controllers\StockLocationController;
Route::group([], function () { Route::group([], function () {
Route::resource('stock', StockController::class)->names('stock'); Route::resource('stock', StockController::class)->names('stock');
Route::resource('stockLocation', StockLocationController::class)->names('stockLocation'); Route::resource('stockLocation', StockLocationController::class)->names('stockLocation');
Route::get('/stocks-by-product', [StockController::class, 'getStocksByProduct'])->name('stocks-by-product');
}); });