Charleskimani
Charleskimani

Reputation: 510

Pass dynamic value to Laravel max validation rule

I am working on a sales laravelcollective form whereby the sale_quantity entered should not be more than the stock_quantity in DB. When I use the idea at: Laravel validate dynamically added input with custom messages there is one answer with:

'orderQty.*' => 'required|numeric|min:1|max:'.$product['productQty']

I have done this as you will see in my function store and function update in the SalesController.php, no error occurs but the form refuses to submit and shows this as a flash message:

The sale quantity may not be greater than '.$stocks['stock_quantity'].

It does not mean what it shows because their is a greater stock_quantity in the database.

SalesController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\DB;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use App\Sale;
use App\Stock;

class SalesController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    function __construct()
    {
        $this->middleware('permission:sales-list');
        $this->middleware('permission:sales-create', ['only' => ['create', 'store']]);
        $this->middleware('permission:sales-edit', ['only' => ['edit', 'update']]);
        $this->middleware('permission:sales-delete', ['only' => ['destroy']]);
}

/**
 * Display a listing of the resource.
 *
 * @return \Illuminate\Http\Response
 */
public function index()
{
    $sales = Sale::orderBy('updated_at', 'desc')->get();
    return view('sales.index')->with('sales', $sales);
}

/**
 * Show the form for creating a new resource.
 *
 * @return \Illuminate\Http\Response
 */
public function create()
{
    $stocks = Stock::all();
    //dd($stocks);
    return view('sales.create', compact('stocks'));
    //$sales = Sale::pluck('stock_id')->prepend('stock_id');
    //$sales = DB::table('stocks')->select('stock_id')->get();
    //return view('sales.create')->with('sales',$sales);
}

public function getUnitSellingPrice(Request $request, $stock_name)
{

    $stock = Stock::where('stock_name', $stock_name)->first();
    if ($stock == null) {
        return null;
    }

    return response()->json($stock->unit_selling_price);
}

public function store(Request $request)
{
    $this->validate($request, [
        'stock_name' => 'required',
        'sale_quantity' => 'required|numeric|min:1|max:\'.$stock[\'stock_quantity\']',
        'unit_selling_price' => 'required',
        'total_sales_cost' => 'required'
    ]);

    //create stock
    $sale = new Sale;
    $sale->stock_name = $request->input('stock_name');
    $sale->sale_quantity = $request->input('sale_quantity');
    $sale->unit_selling_price = $request->input('unit_selling_price');
    $sale->total_sales_cost = $request->input('total_sales_cost');
    $sale->save();
    DB::table('stocks')->where('stock_name', $request->input('stock_name'))->decrement('stock_quantity', $request->input('sale_quantity'));

    return redirect('/sales')->with('success', 'Sale Saved');
}


public function show($sales_id)
{
    $sale = Sale::find($sales_id);
    return view('sales.show')->with('sale', $sale);
}

/**
 * Show the form for editing the specified resource.
 *
 * @param  int $sales_id
 * @return \Illuminate\Http\Response
 */
public function edit($sales_id)
{
    $sale = Sale::findOrFail($sales_id);
    $stocks = Stock::latest('stock_name', 'unit_selling_price')->get();
    return view('sales.edit', compact('sale', 'stocks'));
}

/**
 * Update the specified resource in storage.
 *
 * @param  \Illuminate\Http\Request $request
 * @param  int $sales_id
 * @return \Illuminate\Http\Response
 */
public function update(Request $request, $sales_id)
{
    $this->validate($request, [
        'stock_name' => 'required',
        'sale_quantity' => 'required|numeric|min:1|max:\'.$stock[\'stock_quantity\']',
        'unit_selling_price' => 'required',
        'total_sales_cost' => 'required'

    ]);

    //create stock
    $sale = Sale::find($sales_id);
    $sale->stock_name = $request->input('stock_name');
    $sale->sale_quantity = $request->input('sale_quantity');
    $sale->unit_selling_price = $request->input('unit_selling_price');
    $sale->total_sales_cost = $request->input('total_sales_cost');
    $sale->save();

    return redirect('/sales')->with('success', 'Sale Updated');
}

/**
 * Remove the specified resource from storage.
 *
 * @param  int $sales_id
 * @return \Illuminate\Http\Response
 */
public function destroy($sales_id)
{
    $sale = Sale::find($sales_id);
    $sale->delete();
    return redirect('/sales')->with('success', 'Sale Removed');
}
}

create.blade.php

@extends('layouts.app')

@section('content')
    <br>
    <h1>Add Sale</h1>
    {!! Form::open(['action' => 'SalesController@store', 'method' => 'POST', 'enctype' => 'multipart/form-data']) !!}

<div class="form-group">
    <label>Product Name</label>
    <select name="stock_name" id="stock_name" class="form-control">
        @foreach ($stocks as $stock)
            <option value="{{ $stock->stock_name }}">{{ $stock->stock_name}}</option>
        @endforeach
    </select>
</div>

<div class="form-group">
    {{Form::label('sale_quantity', 'Quantity')}}
    {{Form::text('sale_quantity', '', ['class' => 'form-control', 'placeholder' => 'Quantity', 'id' => 'sales_quantity'])}}
</div>

<div class="form-group">
    {{Form::label('unit_selling_price', 'Unit Selling Price')}}
    {{Form::text('unit_selling_price', '', ['class' => 'form-control', 'placeholder' => 'Unit Selling Price', 'id' => 'unit_selling_price'])}}
</div>

<div class="form-group">
    {{Form::label('total_sales_cost', 'Total Sales Cost')}}
    {{Form::text('total_sales_cost', '', ['class' => 'form-control', 'placeholder' => 'Total Sales Cost', 'id' => 'total_sales_cost', 'readonly' => 'true', 'cursor: pointer' => 'true' ])}}
</div>

{{Form::submit('Submit', ['class' => 'btn btn-primary'])}}
{!! Form::close() !!}

<script>
    $(document).ready(function () {
        $("#stock_name").on('change', function () {
            var stock_name = $(this).val();
            $.ajax({
                url: '/sales-price/getunitsellingprice/'+stock_name,
                method: 'GET',
                success: function (response) {
                    console.log(response);
                    $("#unit_selling_price").val(response);
                },
            });
        });
    });
</script>


<script>
    $(document).ready(function () {
        $("#total_sales_cost").click(function () {
            var sales_quantity = $("#sales_quantity").val();

            var unit_selling_price = $("#unit_selling_price").val();
            var total_sales_cost = (sales_quantity * unit_selling_price);

            $('#total_sales_cost').val(total_sales_cost);
        });
    });
</script>
@endsection

Upvotes: 2

Views: 7893

Answers (2)

Charleskimani
Charleskimani

Reputation: 510

SalesController.php changes at function store and update. Those are the only changes, the blade was Okay.

<?php

namespace App\Http\Controllers;

use App\Http\Requests;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use App\Sale;
use DB;
use App\Stock;

class SalesController extends Controller
{
    function __construct()
    {
        $this->middleware('permission:sales-list');
        $this->middleware('permission:sales-create', ['only' => ['create', 'store']]);
        $this->middleware('permission:sales-edit', ['only' => ['edit', 'update']]);
        $this->middleware('permission:sales-delete', ['only' => ['destroy']]);
    }
    public function index()
    {
        $sales = Sale::orderBy('updated_at', 'desc')->get();
        return view('sales.index')->with('sales', $sales);
    }

    public function create()
    {
        $stocks = Stock::all();
        //dd($stocks);
        return view('sales.create', compact('stocks'));
        //$sales = Sale::pluck('stock_id')->prepend('stock_id');
        //$sales = DB::table('stocks')->select('stock_id')->get();
        //return view('sales.create')->with('sales',$sales);
    }

    public function getUnitSellingPrice(Request $request, $stock_name)
    {
        $stock = Stock::where('stock_name', $stock_name)->first();
        if ($stock == null) {
            return null;
        }
        return response()->json($stock->unit_selling_price);
    }

    public function getStockUnitCost(Request $request, $stock_name)
    {
        $stock = Stock::where('stock_name', $stock_name)->first();
        if ($stock == null) {
            return null;
        }
        return response()->json($stock->stock_unit_cost);
    }

    public function salesWebReport(){
        $sales = Sale::orderBy('updated_at', 'desc')->get();
        return view('sales.saleswebreport')->with('sales', $sales);
    }

    public function photocopying(){
        $stocks = Stock::all();
        //dd($stocks);
        return view('sales.photocopy', compact('stocks'));
    }

    public function store(Request $request)
    {
        //get retrieves an array
        //$stock = \App\Stock::where('stock_name', $request->input('stock_name'))->get();

        //first retrieves an array BUT removes everything and produces only the required field value
        $stock = Stock::where('stock_name', $request->input('stock_name'))->firstOrFail();
        $qty = $stock->stock_quantity;

        $this->validate($request, [
            'stock_name' => 'required',
            'sale_quantity' => 'required|numeric|min:1|max:'.$qty,
            'unit_selling_price' => 'required',
            'total_sales_cost' => 'required',
            'stock_profit' => 'required'
        ]);
        //create stock
        $sale = new Sale;
        $sale->stock_name = $request->input('stock_name');
        $sale->sale_quantity = $request->input('sale_quantity');
        $sale->unit_selling_price = $request->input('unit_selling_price');
        $sale->total_sales_cost = $request->input('total_sales_cost');
    $sale->stock_profit = $request->input('stock_profit');
    $sale->save();
    DB::table('stocks')->where('stock_name', $request->input('stock_name'))->decrement('stock_quantity', $request->input('sale_quantity'));

    return redirect('/sales')->with('success', 'Sale Saved');
}

public function show($sales_id)
{
    $sale = Sale::find($sales_id);
    return view('sales.show')->with('sale', $sale);
}

public function edit($sales_id)
{
    $sale = Sale::findOrFail($sales_id);
    $stocks = Stock::latest('stock_name', 'unit_selling_price')->get();
    return view('sales.edit', compact('sale', 'stocks'));
}
public function update(Request $request, $sales_id)
{
    //get retrieves an array
    //$stock = \App\Stock::where('stock_name', $request->input('stock_name'))->get();

    //first retrieves an array BUT removes everything and produces only the required field value
    $stock = Stock::where('stock_name', $request->input('stock_name'))->firstOrFail();
    $qty = $stock->stock_quantity;

    $this->validate($request, [
        'stock_name' => 'required',
        'sale_quantity' => 'required|numeric|min:1|max:'.$qty,
        'unit_selling_price' => 'required',
        'total_sales_cost' => 'required',
        'stock_profit' => 'required'
    ]);
    //create stock
    $sale = Sale::find($sales_id);
    $sale->stock_name = $request->input('stock_name');
    $sale->sale_quantity = $request->input('sale_quantity');
    $sale->unit_selling_price = $request->input('unit_selling_price');
    $sale->total_sales_cost = $request->input('total_sales_cost');
    $sale->stock_profit = $request->input('stock_profit');
    $sale->save();

    return redirect('/sales')->with('success', 'Sale Updated');
}

public function destroy($sales_id)
{
    $sale = Sale::find($sales_id);
    $sale->delete();
    return redirect('/sales')->with('success', 'Sale Removed');
}
}

Upvotes: 1

Watercayman
Watercayman

Reputation: 8178

According to the error shown, it may be that it is taking your variable and array data as a literal string in this line:

'sale_quantity' => 'required|numeric|min:1|max:\'.$stock[\'stock_quantity\']',

Give a try with php double quotes:

'sale_quantity' => "required|numeric|min:1|max:$stock['stock_quantity']",

Or, to make it even easier for the interpreter, assign a simple variable before the validation step:

 $qty = $stock['stock_quantity'];

and then in the validator:

'sale_quantity' => "required|numeric|min:1|max:$qty",

You may wish to consider using some type of validation on the client side to make this even stronger as well as to help users. Perhaps pass that $qty value from your edit/create methods on your controller to the blade page, and then use something like JQuery Validation to check on the form before the user even submits it to the server.

So - to solve it, something like this:

public function store(Request $request)
{
  $stock = \App\Stock::find($someIdOfYourChoiceOrFromTheForm)
  $qty = $stock->stock_quantity;

  $this->validate($request, [
    'stock_name' => 'required',
    'sale_quantity' => "required|numeric|min:1|max:$qty",
    'unit_selling_price' => 'required',
    'total_sales_cost' => 'required'
   ]);

Upvotes: 0

Related Questions