I've the input function for outbound materials from warehouse like so :
[
"movement_date" => "2022-09-08",
"type" => "1",
"transaction_number" => "OUTBOUND-001",
"remarks" => "Moved to another warehouse",
"items" => [
0 => [
"material_id" => "47",
"uom" => "Kilogram",
"qty" => "1000",
],
1 => [
"material_id" => "16",
"uom" => "Kilogram",
"qty" => "500",
],
],
]
In FormRequest i tried to check the remaining stocks for each materials like so :
return [
'type' => 'required',
'movement_date' => ['required','date', function ($attribute, $value, $fail) {
if ($value > Carbon::now()->format('Y-m-d')) $fail('Invalid date '.Carbon::now()->format('Y-m-d'));
}],
'items' => 'required|array',
'items.*.material_id' => 'required',
'items.*.qty' => ['required', function ($attribute, $value, $fail) {
$stock = \App\Models\MaterialStock::where('material_id', 'I need material id from material_id field here')->first();
$stock === null ? $balance = 0 : $balance = $stock->qty;
if ($balance < $value) $fail('Insufficient stock');
}],
];
The question is, how do i get the "material_id" value when i'm trying to validate the qty field ?
CodePudding user response:
As suggested by @matiaslauriti, i did solve the problem by utilizing Laravel's object validator
First, i need to create the Rules which implements DataAwareRule to interact with other field values :
class HasStock implements Rule, DataAwareRule
{
protected $data = [];
public function setData($data)
{
$this->data = $data;
return $this;
}
public function passes($attribute, $value)
{
$index = explode('.',$attribute)[1];
$materialId = $this->data['items'][$index]['material_id'];
$stock = \App\Models\MaterialStock::where('material_id', $materialId)->first();
$stock === null ? $balance = 0 : $balance = $stock->stock;
return $balance > $value;
}
public function message()
{
return 'Insufficient stock.';
}
}
Then i can initializing the HasStock Rules instance from the Form Request like so :
public function rules()
{
return [
'type' => 'required',
'movement_date' => ['required','date', function ($attribute, $value, $fail) {
if ($value > Carbon::now()->format('Y-m-d')) $fail('Invalid date.');
}],
'items' => 'required|array',
'items.*.material_id' => 'required',
'items.*.qty' => ['required', new HasStock],
];
}
The result was exaclty i was looking for, it did validate the stocks correctly.
CodePudding user response:
Here is your solution:
$rules = [
// ...
'items' => ['required', 'array'],
];
foreach($this->items as $key => $item){
$rules['items.'.$key.'.material_id'] = ['required'];
$rules['items.'.$key.'.qty'] = ['required', function($attribute, $value, $fail) use ($key) {
$stock = \App\Models\MaterialStock::where('material_id', $this->items[$key]['material_id'])->first();
$balance = $stock === null ? 0 : $stock->qty;
if ($balance < $value) $fail('Insufficient stock');
}];
}
return $rules;