Restaurant Management System ( Part 11 )

Published Date: 28-Feb-2018 | Tags: Laravel 5.5  Bootstrap 3  Project  

This tutorial I want to show you all sale operations in Cashier screen.

Cashier features

  • Click Product to Order
  • Order by Product Code
  • Filter Product
  • Move Table
  • Open Product ( if no product for selection, we can type)
  • Split Bill
  • Update Product Description, Qty, and Unitprice
  • Discount
  • VIP Customer

Note: I recommend you to check all pervious tutorials before coming to this step. Because some tutorials have relationship with others.

 

Step 1: Create Model

Create model Order.php in /demo/app.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    public function order_details()
    {
        return $this->hasMany('App\OrderDetail');
    }

    public function table()
    {
        return $this->belongsTo('App\Table');
    }
    public function customer()
    {
        return $this->belongsTo('App\Customer');
    }
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}

 

Create model OrderDetail.php in /demo/app.

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class OrderDetail extends Model
{
    use SoftDeletes;
    protected $dates = ['deleted_at'];

    public function order()
    {
        return $this->belongsTo('App\Order');
    }
    public function menu(){
        return $this->belongsTo('App\Menu');
    }
}

 

Step 2: Create View

Create layout view cashier.blade.php in /resources/views/layouts. (create folder layouts if it does not exist) 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Restaurant Management System</title>
    <!-- Styles -->
    <link href="{{ asset('bootstrap-3.3.7/css/bootstrap.min.css') }}" rel="stylesheet">
    <link href="{{ asset('css/style.css') }}" rel="stylesheet">
    <link href="{{ asset('css/sale.css') }}" rel="stylesheet">
</head>
<body style="background: grey">
<div class="modal fade " id="modal" tabindex="-1" role="dialog" aria-labelledby="modal"
     aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content container-fluid">
        </div>
    </div>
</div>
<div class="modal fade " id="modal_open" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="modal"
     aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content container-fluid">
        </div>
    </div>
</div>
<div class="modal fade " id="modal_pay" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="modal"
     aria-hidden="true">
    <div class="modal-dialog modal-lg">
        <div class="modal-content container-fluid">
        </div>
    </div>
</div>
<div class="container-fluid" style="background: #eef2f4;border-bottom: 5px solid whitesmoke">
    <img src="/images/logo.png" height="50px" width="100px"/>
    <div class="pull-right" style="padding-top: 10px;font-size: 16px">
        Hi, {{ucwords(Auth::user()->username)}} ( <a href="{{url('/logout')}}" onclick="event.preventDefault();
                                             document.getElementById('logout-form').submit();">Logout</a>
        <form id="logout-form" action="{{ route('logout') }}" method="POST"
              style="display: none;">
            {{ csrf_field() }}
        </form>
        )
    </div>
</div>
@yield('content')
<script src="{{ asset('js/jquery-3.1.1.min.js') }}"></script>
<script src="{{ asset('bootstrap-3.3.7/js/bootstrap.min.js') }}"></script>
<script>
    $('#modal, #modal_open, #modal_pay').on('shown.bs.modal', function () {
        $('#focus').focus().select();
    });
    $('#modal, #modal_open, #modal_pay').on('hidden.bs.modal', function (e) {
        $(this).removeData('bs.modal');
    });
    function ajaxLoad(filename, content) {
        content = typeof content !== 'undefined' ? content : 'content';
        $('.loading').show();
        $.ajax({
            type: "GET",
            url: filename,
            contentType: false,
            success: function (data) {
                $("#" + content).html(data);
                $('.loading').hide();
            },
            error: function (xhr, status, error) {
                if (xhr.responseText == 'Unauthorized.')
                    location.reload();
                else
                    alert(xhr.responseText);
            }
        });
    }
    function ajaxDelete(filename, token, content) {
        content = typeof content !== 'undefined' ? content : 'content';
        $('.loading').show();
        $.ajax({
            type: 'POST',
            data: {_method: 'DELETE', _token: token},
            url: filename,
            success: function (data) {
                $("#" + content).html(data);
                $('.loading').hide();
            },
            error: function (xhr, status, error) {
                alert(xhr.responseText);
            }
        });
    }
</script>
</body>
</html>

 

Create view _form.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<div class="modal-body">
    <div class="row">
        <div class="form-group required" id="form-description-error">
            {!! Form::label("description","Description",["class"=>"control-label"]) !!}
            {!! Form::text("description",null,["class"=>"form-control required","id"=>"focus","autocomplete"=>"off"]) !!}
            <span id="description-error" class="help-block"></span>
        </div>
        <div class="form-group required" id="form-quantity-error">
            {!! Form::label("quantity","Quantity",["class"=>"control-label"]) !!}
            {!! Form::text("quantity",null,["class"=>"form-control required","autocomplete"=>"off"]) !!}
            <span id="quantity-error" class="help-block"></span>
        </div>
        <div class="form-group required" id="form-price-error">
            {!! Form::label("price","Price",["class"=>"control-label"]) !!}
            {!! Form::text("price",null,["class"=>"form-control required","autocomplete"=>"off"]) !!}
            <span id="price-error" class="help-block"></span>
        </div>
    </div>
</div>
<div class="modal-footer">
    {!! Form::button("<i class='glyphicon glyphicon-remove'></i> Close",["class"=>"btn
    btn-primary","data-dismiss"=>"modal"])!!}
    {!! Form::button("<i class='glyphicon glyphicon-floppy-disk'></i> Save",["type" => "submit","class"=>"btn
    btn-primary","id"=>"btn_save"])!!}
</div>

 

Create view _order.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<style>
    input[type=text]:focus {
        background: lightyellow;
    }
</style>
<div class="row" style="padding-left: 20px">
    <a title="Table" class="btn btn-warning pay" data-toggle="modal" data-target="#modal"
       href="cashier/table">
        <b id="table_id">{{Session::has('table_id')?\App\Table::find(Session::get('table_id'))->name:'Table #'}}</b>
    </a>
    <a class="btn btn-primary pay"
       data-toggle="modal" data-target="#modal" href="cashier/change-table">
        Change
    </a>
    <a class="btn btn-primary pay" data-toggle="modal"
       data-target="#modal_open" href="cashier/open">
        Open
    </a>
    <div class="pay" style="background: none;padding-left: 0px;padding-right: 0px;padding-top: 5px">
        <input @if(Session::get('table_id')=='') disabled @endif type="text" class="form-control" placeholder="Code"
               onkeydown="if (event.keyCode == 13) ajaxLoad('cashier/order/'+this.value,'orderList')"/>
    </div>
    <a style="@if(Session::get('table_id')=='' || count($order)==0) pointer-events: none @endif"
       href="{{url("cashier/print")}}"
       target="_blank" class="btn btn-danger pay">
        Print
    </a>
    <a class="btn btn-success pay" data-toggle="modal" data-target="#modal_pay" href="cashier/pay"
       style="@if(Session::get('table_id')=='' || count($order)==0) pointer-events: none @endif">
        Pay
    </a>
</div>
<div class="row" style="background: white;padding: 10px 10px 30px 10px">
    <table class="table">
        <thead>
        <tr>
            <th style="margin: 0px;padding: 0px;vertical-align: middle" width="1px"></th>
            <th>Description</th>
            <th style="text-align: center">Qty</th>
            <th style="text-align: right;">Price</th>
            <th style="text-align: right">Total</th>
            <th style="width: 1px"></th>
        </tr>
        </thead>
        @if(count($order)>0)
            <?php $total = 0; ?>
            <tbody>
            @foreach($order->order_details()->orderBy('description')->get() as $orderDetail)
                <tr style="color: darkblue;@if(($orderDetail->status=='Filled')) color: red; @endif @if(!empty($orderDetail->deleted_at)) text-decoration: line-through; @endif">
                    <td style="margin: 0px;padding: 0px;vertical-align: middle">
                        <input type="checkbox" style="width: 18px;height: 18px" value="{{$orderDetail->id}}"
                               class="idRow"/>
                    </td>
                    <td style="@if($orderDetail->sent==1) color:red; @endif">
                        <input onchange="ajaxLoad('cashier/update-description/{{$orderDetail->id}}/'+this.value,'orderList')"
                               type="text" style="width: 100%;border: none;height: 30px"
                               value="{{$orderDetail->description}}"/>
                    </td>
                    <td align="center">
                        <input onfocus="$(this).select()"
                               onchange="ajaxLoad('cashier/update-quantity/{{$orderDetail->id}}/'+this.value,'orderList')"
                               type="text" style="width: 20px;border: none;height: 30px;text-align: center"
                               value="{{$orderDetail->quantity}}"/>
                    </td>
                    <td align="right">
                        <input onfocus="$(this).select()"
                               onchange="ajaxLoad('cashier/update-price/{{$orderDetail->id}}/'+this.value,'orderList')"
                               type="text" style="width: 30px;border: none;height: 30px;text-align: right"
                               value="{{number_format($orderDetail->price,2)}}"/>
                    </td>
                    <td align="right">
                        <input type="text" style="width: 50px;border: none;height: 30px;text-align: right" readonly
                               value="$ {{number_format($orderDetail->price * $orderDetail->quantity*(1-$orderDetail->discount/100),2)}}"/>

                    </td>
                    <td style="text-align: center;padding-top: 15px">
                        @if($orderDetail->status!='Filled' or (isset($orderDetail->product_id) and $orderDetail->product_id==0))
                            <a href="javascript:if(confirm('Are you sure want to delete?')) ajaxDelete('cashier/delete/{{$orderDetail->id}}','{{csrf_token()}}','orderList')">
                                <i class="glyphicon glyphicon-minus-sign" style="color: brown;"></i></a>
                        @endif
                    </td>
                </tr>
                <?php if (empty($orderDetail->deleted_at)) $total += ($orderDetail->price * $orderDetail->quantity * (1 - $orderDetail->discount / 100)); ?>
            @endforeach
            </tbody>
        @endif
    </table>
    @if(count($order)>0)
        <div style="text-align: right;float: right;border-top: solid 1px whitesmoke;">
            <table width="100%">
                <tr>
                    <th style="text-align: right;padding-right: 20px">Customer:</th>
                    <th style="text-align: right">
                        {!! Form::select('customer',['0'=>'General']+\App\Customer::orderBy('name')->pluck('name','id')->toArray() ,$order->customer_id,['style'=>'border:none','onChange'=>"ajaxLoad('cashier/update-customer/".$order->id."/'+this.value,'orderList')"]) !!}
                    </th>
                </tr>
                <tr>
                    <th style="text-align: right;padding-right: 20px">Discount:</th>
                    <th style="text-align: right"><input onfocus="$(this).select()"
                                                         onchange="ajaxLoad('cashier/update-discount/{{$order->id}}/'+this.value,'orderList')"
                                                         type="text"
                                                         style="width: 50px;border: none;text-align: right"
                                                         value="@if(Session::get('order_id')!=''){{$order->discount}} @endif"/>
                        %
                    </th>
                </tr>
                <tr>
                    <th style="text-align: right;padding-right: 20px">Total:</th>
                    <th style="text-align: right">$ {{number_format($total*(1-$order->discount/100),2)}}</th>
                </tr>
            </table>
        </div>
</div>
@endif
<script>
    function getSelectedRows() {
        var selected = [];
        $(".idRow:checked").each(function () {
            selected.push($(this).attr('value'));
        });
        return selected;
    }
</script>

 

Create view _pay.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<div class="modal-body">
    <div class="row">
        <div class="col-md-7">
            <table class="table">
                <thead>
                <tr>
                    <th>Description</th>
                    <th>Qty</th>
                    <th>Price</th>
                    <th>Total</th>
                </tr>
                </thead>
                @if(count($order)>0)
                    <tbody>
                    <?php $total = 0; ?>
                    @foreach($order->order_details()->select(DB::raw("description,sum(quantity) as quantity,price,discount"))->groupBy('product_id')->groupBy('price')->groupBy('description')->groupBy('discount')->orderBy('description')->get() as $orderDetail)
                        <tr @if(!empty($orderDetail->deleted_at)) style="text-decoration: line-through;" @endif>
                            <td>
                                {{$orderDetail->description}}
                            </td>
                            <td>
                                {{$orderDetail->quantity}}
                            </td>
                            <td align="right">$ {{number_format($orderDetail->price,2)}}</td>
                            <td align="right">
                                $ {{number_format($orderDetail->price * $orderDetail->quantity* (1 - $orderDetail->discount / 100),2)}}</td>
                        </tr>
                        <?php if (empty($orderDetail->deleted_at)) $total += ($orderDetail->price * $orderDetail->quantity * (1 - $orderDetail->discount / 100)); ?>
                    @endforeach
                    </tbody>
                @endif
            </table>
            @if(count($order)>0)
                <div style="text-align: right;float: right;border-top: solid 1px whitesmoke;">
                    <table width="100%">
                        <tr>
                            <th style="text-align: right;padding-right: 20px">Discount:</th>
                            <th style="text-align: right">{{$order->discount}} %</th>
                        </tr>
                        <tr>
                            <th style="text-align: right;padding-right: 20px">Total:</th>
                            <th style="text-align: right">$ {{number_format($total*(1-$order->discount/100),2)}}</th>
                        </tr>
                    </table>
                </div>
            @endif
        </div>
        <div class="col-md-5">
            <div class="form-group required" id="form-usd-error">
                {!! Form::label("usd","Cash in USD",["class"=>"control-label"]) !!}
                {!! Form::text("usd",0,["class"=>"form-control required","id"=>"focus","autocomplete"=>"off"]) !!}
                <span id="usd-error" class="help-block"></span>
            </div>
        </div>
    </div>
</div>
<div class="modal-footer">
    <p id="msg" style="display: none;color: blue;float: left;">{{env('success_msg')}}</p>
    {!! Form::button("<i class='glyphicon glyphicon-remove'></i> Close",["class"=>"btn
    btn-primary","data-dismiss"=>"modal"])!!}
    {!! Form::button("<i class='glyphicon glyphicon-floppy-disk'></i> Save",["type" => "submit","class"=>"btn
    btn-primary","id"=>"btn_save"])!!}
</div>

 

Create view change_table.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
    </button>
    <h4 class="modal-title">Change from Table <b
                style="color: red">{{\App\Table::find(Session::get('table_id'))->name}} </b> to</h4>
</div>
<div class="modal-body">
    <div class="row">
        @foreach($tables as $table)
            <div class="tbl {{$table->status}}"
                 onclick="ajaxLoad('cashier/switch-table/{{$table->id}}?ids='+getSelectedRows(),'orderList');$('#modal').modal('hide');">{{$table->name}}
            </div>
        @endforeach
    </div>
</div>

 

Create view index.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

@extends('layouts.cashier')
@section('content')
    <div class="container-fluid" style="margin-top: 10px">
        <div class="col-md-4" style="padding: 0px">
            @foreach($menuCategories as $menuCategory)
                <div class="menu @if($menuCategory->id==(Session::has('menuCategory_id')?Session::get('menuCategory_id'):env('DEFAULT_MENU_CATEGORY'))) active  @endif"
                     onclick="$('.menu').removeClass('active');$(this).addClass('active');ajaxLoad('cashier/products?menuCategory_id={{$menuCategory->id}}','productList')">{{$menuCategory->name}}
                </div>
            @endforeach
        </div>
        <div class="col-md-4">
            <input type="text" class="form-control"
                   style="border: 2px solid whitesmoke;height: 50px;border-radius: 0px;background: lightyellow;font-size: 18px"
                   onfocus="$(this).select()"
                   onkeyup="ajaxLoad('cashier/products?search='+this.value,'productList')"/>
            <div id="productList">
                <ul class="list-group"
                    style="height: 520px;overflow-y: auto;border: 2px outset;background: white">
                    @foreach(\App\Product::where('product_category_id',Session::get('menuCategory_id'))->orderBy('name')->get() as $menu)
                        <li class="list-group-item"
                            style="font-size: 16px;padding:0px;height: 80px"
                            onclick="if($('#table_id').text()=='Table #') alert('Please select table first'); else ajaxLoad('cashier/order/{{$menu->id}}','orderList')">
                            <img src="{{$menu->image!='' && File::exists('images/products/'.$menu->image)?'/images/products/'.$menu->image:'/images/default.jpg'}}"
                                 class="pull-left" width="80px" height="70px"
                                 style="margin: 5px 5px 0px 5px"/>
                            <div style="margin:20px">
                                <span style="color: red;font-size: 15px"
                                      class="pull-right">${{number_format($menu->unitprice,2)}}</span>
                                <div>{{$menu->name}} <span style="color: gray">({{$menu->id}})</span></div>
                            </div>
                        </li>
                    @endforeach
                </ul>
            </div>
        </div>
        <div class="col-md-4" id="orderList">
            @include('cashier._order')
        </div>
    </div>
@endsection

 

Create view open.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
    </button>
    <h4 class="modal-title">Open Order</h4>
</div>
{!! Form::open(["id"=>"updateForm"]) !!}
@include("cashier._form")
{!! Form::close() !!}
<script>
    $("#updateForm").submit(function (event) {
        $("#btn_save").attr('disabled', 'disabled').html("<i class='glyphicon glyphicon-floppy-disk'></i> Saving...");
        event.preventDefault();
        $("#updateForm input").css("pointer-events", "none");
        $('.loading').show();
        var form = $(this);
        var data = form.serialize();
        var url = form.attr("action");
        $.ajax({
            type: "POST",
            url: url,
            data: data,
            cache: false,
            success: function (data) {
                if (data.fail) {
                    $('input.required, textarea.required').each(function () {
                        index = $(this).attr('name');
                        if (index in data.errors) {
                            $("#form-" + index + "-error").addClass("has-error");
                            $("#" + index + "-error").html(data.errors[index]);
                        }
                        else {
                            $("#form-" + index + "-error").removeClass("has-error");
                            $("#" + index + "-error").empty();
                        }
                    });
                } else {
                    $(".has-error").removeClass("has-error");
                    $(".help-block").empty();
                    $("#modal_open").find('form')[0].reset();
                    $('#modal_open').modal('hide');
                    $("#orderList").html(data);
                }
                $('.loading').hide();
                $("#btn_save").removeAttr('disabled').html("<i class='glyphicon glyphicon-floppy-disk'></i> Save");
                $("#updateForm input").css("pointer-events", "");
            },
            error: function (xhr, textStatus, errorThrown) {
                alert(textStatus);
                $("#btn_save").removeAttr('disabled').html("<i class='glyphicon glyphicon-floppy-disk'></i> Save");
                $("#updateForm input").css("pointer-events", "");
            }
        });
        return false;
    });
</script>

 

Create view pay.blade.php in /resources/views/cashier. (create folder cashier if it does not exist) 

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
    </button>
    <h4 class="modal-title">Payment</h4>
</div>
{!! Form::open(["id"=>"updateForm"]) !!}
@include("cashier._pay")
{!! Form::close() !!}
<script>
    $("#updateForm").submit(function (event) {
        $("#btn_save").attr('disabled', 'disabled').html("<i class='glyphicon glyphicon-floppy-disk'></i> Saving...");
        event.preventDefault();
        $("#updateForm input").css("pointer-events", "none");
        $('.loading').show();
        var form = $(this);
        var data = form.serialize();
        var url = form.attr("action");
        $.ajax({
            type: "POST",
            url: url,
            data: data,
            cache: false,
            success: function (data) {
                if (data.fail) {
                    $('input.required, textarea.required').each(function () {
                        index = $(this).attr('name');
                        if (index in data.errors) {
                            $("#form-" + index + "-error").addClass("has-error");
                            $("#" + index + "-error").html(data.errors[index]);
                        }
                        else {
                            $("#form-" + index + "-error").removeClass("has-error");
                            $("#" + index + "-error").empty();
                        }
                    });
                } else {
                    $(".has-error").removeClass("has-error");
                    $(".help-block").empty();
                    $("#modal_pay").find('form')[0].reset();
                    $('#modal_pay').modal('hide');
                    ajaxLoad('{{url('cashier/return-order')}}','orderList');
                    window.open('{{url("cashier/print-payment")}}');
                }
                $('.loading').hide();
                $("#btn_save").removeAttr('disabled').html("<i class='glyphicon glyphicon-floppy-disk'></i> Save");
                $("#updateForm input").css("pointer-events", "");
            },
            error: function (xhr, textStatus, errorThrown) {
                alert(textStatus);
                $("#btn_save").removeAttr('disabled').html("<i class='glyphicon glyphicon-floppy-disk'></i> Save");
                $("#updateForm input").css("pointer-events", "");
            }
        });
        return false;
    });
</script>

 

Create view table.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span>
    </button>
    <h4 class="modal-title">Select Table</h4>
</div>
<div class="modal-body">
    <div class="row">
        @foreach($tables as $table)
            <div class="tbl {{$table->status}}"
                 onclick="ajaxLoad('cashier/select-table/{{$table->id}}','orderList');$('#modal').modal('hide');">{{$table->name}}
            </div>
        @endforeach
    </div>
</div>

 

Create view print.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<center>
    <img src="{{asset('images/logo.png')}}" height=80px" width="150px"/>
    <h2 style="font-size:16px;margin:0">SOURKEA RESTAURANT</h2>
    <i style="font-size:11px;width:90%;display:block">Address: #33, Steet 99, Boeung Trabek, Chamkar Mon, Phnom Penh.
        Tel: 069 868 768, 078 551 115</i>
    <h3 style="padding: 0px;margin: 0px">Invoice</h3>
</center>
<hr style="size:2px;border:inset;margin-top: 0px;padding-top: 0px">
<table style="width:100%;font-size:12px">
    <tr>
        <td width="80px" style="text-align:right">Invoice #:</td>
        <td style="text-align:left">{{str_pad($order->id,6,0,0)}}</td>
        <td style="width:60px;text-align:right">Date:</td>
        <td style="text-align:left;width:100px">{{date("d-M-Y",strtotime($order->updated_at))}}</td>
    </tr>
    <tr>
        <td width="80px" style="text-align:right">Table No:</td>
        <td style="text-align:left">{{$order->table->name}}</td>
        <td style="width:60px;text-align:right">Cashier:</td>
        <td style="text-align:left;width:100px">{{ucwords(Auth::user()->username)}}</td>
    </tr>
    <tr>
        <td width="80px" style="text-align:right">Customer:</td>
        <td style="text-align:left">{{!empty($order->customer_id)&&$order->customer_id!='-1'?$order->customer->name:'General'}}</td>
    </tr>
</table>
<table style="width:100%;margin-top:10px" border="0" cellspacing="0" cellpadding="2px">
    <tr style="font-size:13px">
        <th width="20px">No</th>
        <th>Description</th>
        <th style="width:8%;text-align: center;">Qty</th>
        <th style="width:16%;text-align: right">Price</th>
        {{--<th style="width:12%">D.C</th>--}}
        <th style="width:18%;text-align: right">Total</th>
    </tr>
    <tr style="font-size:14px">
        <th colspan="6" align="left">
            <hr>
        </th>
    </tr>
    <?php $total = 0;$i = 1 ?>
    @foreach($order->order_details()->select(DB::raw("description,sum(quantity) as quantity,price,discount"))->groupBy('product_id')->groupBy('price')->groupBy('description')->groupBy('discount')->orderBy('description')->get() as $orderDetail)
        <tr style="font-size:11px;@if(!empty($orderDetail->deleted_at)) text-decoration: line-through; @endif">
            <td align="center">{{$i++}}</td>
            <td align="left">{{$orderDetail->description}}</td>
            <td align="center">{{$orderDetail->quantity}}</td>
            <td align="right">$ {{number_format($orderDetail->price,2)}}</td>
            {{--<td align="center">{{$orderDetail->discount}}%</td>--}}
            <td align="right">
                $ {{number_format($orderDetail->quantity * $orderDetail->price * (1 - $orderDetail->discount / 100),2)}}</td>
            <?php if (empty($orderDetail->deleted_at)) $total += ($orderDetail->price * $orderDetail->quantity * (1 - $orderDetail->discount / 100)); ?>
        </tr>
    @endforeach
</table>
<hr>
<table width="100%">
    <tr>
        <td align="right">
            <table width="100%" style="font-size: 12px">
                @if($order->discount>0)
                    <tr>
                        <th style="text-align: right;padding-right: 20px">Grand Total:</th>
                        <th style="text-align: right">$ {{number_format($total,2)}}</th>
                    </tr>
                    <tr>
                        <th style="text-align: right;padding-right: 20px">Discount ({{$order->discount}}%):</th>
                        <th style="text-align: right">$ {{number_format($order->discount*$total/100,2)}}</th>
                    </tr>
                @endif
                <tr>
                    <th style="text-align: right;padding-right: 20px">Net Amount:</th>
                    <th style="text-align: right">$ {{number_format($total*(1-$order->discount/100),2)}}</th>
                </tr>
            </table>
        </td>
    </tr>
</table>
<hr>
<center><i style="font-size: 12px">Thank you, see you again!</i></center>
<script>
    //    window.print();
    //    window.close();
</script>

 

Create view print_payment.blade.php in /resources/views/cashier. (create folder cashier if it does not exist)

<center>
    <img src="{{asset('images/logo.png')}}" height="80px" width="150px"/>/>
    <h1 style="font-size:20px;margin:0">SOURKEA RESTAURANT</h1>
    <i style="font-size:11px;width:90%;display:block">Address: #33, Steet 99, Boeung Trabek, Chamkar Mon, Phnom Penh.
        Tel: 069 868 768, 078 551 115 </i>
    <h3 style="padding: 0px;margin: 0px">Receipt</h3>
</center>
<hr style="size:2px;border:inset;margin-top: 0px;padding-top: 0px">
<table style="width:100%;font-size:12px">
    <tr>
        <td width="80px" style="text-align:right">Invoice #:</td>
        <td style="text-align:left">{{str_pad($order->id,6,0,0)}}</td>
        <td style="width:60px;text-align:right">Date:</td>
        <td style="text-align:left;width:100px">{{date("d-M-Y",strtotime($order->updated_at))}}</td>
    </tr>
    <tr>
        <td width="80px" style="text-align:right">Table No:</td>
        <td style="text-align:left">{{$order->table->name}}</td>
        <td style="width:60px;text-align:right">Cashier:</td>
        <td style="text-align:left;width:100px">{{ucwords(Auth::user()->username)}}</td>
    </tr>
    <tr>
        <td width="80px" style="text-align:right">Customer:</td>
        <td style="text-align:left">{{!empty($order->customer_id)&&$order->customer_id!='-1'?$order->customer->name:'General'}}</td>
    </tr>
</table>
<table style="width:100%;margin-top:10px" border="0" cellspacing="0" cellpadding="2px">
    <tr style="font-size:13px">
        <th width="20px">No</th>
        <th>Description</th>
        <th style="width:8%;text-align: center">Qty</th>
        <th style="width:16%;text-align: right">Price</th>
        <th style="width:18%;text-align: right">Total</th>
    </tr>
    <tr style="font-size:14px">
        <th colspan="6" align="left">
            <hr>
        </th>
    </tr>
    <?php $total = 0; $i = 1;?>
    @foreach($order->order_details()->select(DB::raw("description,sum(quantity) as quantity,price,discount"))->groupBy('product_id')->groupBy('price')->groupBy('description')->groupBy('discount')->orderBy('description')->get() as $orderDetail)
        <tr style="font-size:11px;@if(!empty($orderDetail->deleted_at)) text-decoration: line-through; @endif">
            <td align="center">{{$i++}}</td>
            <td align="left">{{$orderDetail->description}}</td>
            <td align="center">{{$orderDetail->quantity}}</td>
            <td align="right">$ {{number_format($orderDetail->price,2)}}</td>
            <td align="right">
                $ {{number_format($orderDetail->quantity * $orderDetail->price* (1 - $orderDetail->discount / 100),2)}}</td>
            <?php if (empty($orderDetail->deleted_at)) $total += ($orderDetail->price * $orderDetail->quantity * (1 - $orderDetail->discount / 100)); ?>
        </tr>
    @endforeach
</table>
<hr>
<table width="100%">
    <tr>
        <td align="right">
            <table width="100%" style="font-size: 12px">
                @if($order->discount>0)
                    <tr>
                        <th style="text-align: right;padding-right: 20px">Grand Total ($):</th>
                        <th style="text-align: right">{{number_format($total,2)}}</th>
                    </tr>
                    <tr>
                        <th style="text-align: right;padding-right: 20px">Discount ({{$order->discount}}%):</th>
                        <th style="text-align: right">$ {{number_format($order->discount*$total/100,2)}}</th>
                    </tr>
                @endif
                <tr>
                    <th style="text-align: right;padding-right: 20px">Net Amount ($):</th>
                    <th style="text-align: right">{{number_format($total*(1-$order->discount/100),2)}}</th>
                </tr>
                @if(Session::get('usd')>0)
                    <tr>
                        <th style="text-align: right;padding-right: 20px">Cash in ($):</th>
                        <th style="text-align: right">{{number_format(Session::get('usd'),2)}}</th>
                    </tr>
                @endif
                @if(Session::get('change_us')>0)
                    <tr>
                        <th style="text-align: right;padding-right: 20px">Cash Return ($):</th>
                        <th style="text-align: right">
                            {{number_format(Session::get('change_us'),2)}}</th>
                    </tr>
                @endif
            </table>
        </td>
    </tr>
</table>
<hr/>
<center><i style="font-size: 12px">Thank you, see you again!</i><br>
</center>
<script>
    //    window.print();
    //    window.close();
</script>

 

Step 3: Create Controller

Create controller CashierController.php in /demo/app/Http/Cotrollers.

<?php
namespace App\Http\Controllers;

use App\Customer;
use App\Item;
use App\Product;
use App\ProductCategory;
use App\Order;
use App\OrderDetail;
use App\Recipe;
use App\Table;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;

class CashierController extends Controller
{
    public function index()
    {
        Session::put('menuCategory_id', Input::has('menuCategory_id') ? Input::get('menuCategory_id') : (Session::has('menuCategory_id') ? Session::get('menuCategory_id') : env('DEFAULT_MENU_CATEGORY')));
        if (Session::get('order_id') != '')
            $order = Order::find(Session::get('order_id'));
        else
            $order = [];
        return view('cashier.index', [
            'menuCategories' =>
                ProductCategory::orderBy('ordering')->get(),
            'order' => $order
        ]);
    }

    public function products()
    {
        Session::put('menuCategory_id', Input::has('menuCategory_id') ? Input::get('menuCategory_id') : (Session::has('menuCategory_id') ? Session::get('menuCategory_id') : env('DEFAULT_MENU_CATEGORY')));
        $str = '<ul class="list-group" style="height: 520px;overflow-y: auto;border: 2px outset;background: white">';
        $products = new Product();
        if (Input::has('search') && trim(Input::get('search')) != '')
            $products = $products->where(function ($q) {
                $q->where('name', 'like', '%' . trim(Input::get('search')) . '%')
                    ->orWhere('id', trim(Input::get('search')));
            });
        if (Input::has('menuCategory_id') || trim(Input::get('search')) == '')
            $products = $products->where('product_category_id', Session::get('menuCategory_id'));
        $products = $products->orderBy('name')->get();
        foreach ($products as $menu) {
            $str .= '<li class="list-group-item" style="font-size: 16px;padding:0px;height: 80px"
            onclick="if($(\'#table_id\').text()==\'Table #\') alert(\'Please select table first\'); else ajaxLoad(\'cashier/order/' . $menu->id . '\',\'orderList\');">
            <img src=' . ($menu->image != '' && File::exists("images/products/" . $menu->image) ? "/images/products/" . $menu->image : "/images/default.jpg") . ' class="pull-left" width="80px" height="70px"
                                 style="margin: 5px 5px 0px 5px"/>
                            <div style="margin:20px">
                                <span style="color: red;font-size: 15px"
                                      class="pull-right">$' . number_format($menu->unitprice, 2) . '</span>
                                <div>' . $menu->name . ' <span style="color: gray">(' . $menu->id . ')</span></div>
                            </div></li>';
        }
        $str .= '</ul>';
        return $str;
    }

    public function order($id)
    {
        $menu = Product::find($id);
        if (count($menu) > 0 or ($id == 0 and env('KTV'))) {
            $order = Order::find(Session::get('order_id'));
            if (count($order) == 0) {
                $order = new Order();
                $order->table_id = Session::get('table_id');
                $order->checked_in = date('Y-m-d H:i:s');
                $order->user_id = Auth::user()->id;
            }
            $order->status = 'Busy';
            $order->table->status = 'Busy';
            $order->push();
            $order_detail = OrderDetail::where('order_id', $order->id)->where('product_id', $id)->first();
            if (count($order_detail) == 0) {
                $order_detail = new OrderDetail();
                $order_detail->order_id = $order->id;
                $order_detail->product_id = $id;
                $order_detail->ordered_date = $order->created_at;
                if ($id > 0)
                    $order_detail->quantity = 1;
                $order_detail->description = $menu->name;
                $order_detail->price = $menu->unitprice;
                $order_detail->user_id = Auth::user()->id;
                $order_detail->save();
            } else {
                if ($id > 0)
                    $order_detail->quantity += 1;
                $order_detail->user_id = Auth::user()->id;
                $order_detail->save();
            }
            Session::put('order_id', $order->id);
        }
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function updateDescription($id, $value)
    {
        $orderDetail = OrderDetail::where('id', $id)->first();
        if (count($orderDetail)) {
            $orderDetail->description = $value;
            $orderDetail->save();
        }
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function updateQuantity($id, $value)
    {
        $orderDetail = OrderDetail::where('id', $id)->first();
        if (count($orderDetail)) {
            $orderDetail->quantity = $value;
            $orderDetail->save();
        }
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function updatePrice($id, $value)
    {
        $orderDetail = OrderDetail::where('id', $id)->first();
        if (count($orderDetail)) {
            $orderDetail->price = $value;
            $orderDetail->save();
        }
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function updateCustomer($id, $value)
    {
        $order = Order::find($id);
        $order->customer_id = $value;
        $order->discount = $value > 0 ? Customer::find($value)->discount : 0;
        $order->save();
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function updateDiscount($id, $value)
    {
        $order = Order::find($id);
        $order->discount = $value;
        $order->save();
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function switchTable($id)
    {
        Session::put('table_id', $id);
        $ids = Input::get('ids');
        $oldorder = Order::find(Session::get('order_id'));
        $neworder = Order::where('table_id', Session::get('table_id'))->where('status', '!=', 'Completed')->where('status', '!=', 'Moved')->where(DB::raw('date(created_at)'), date('Y-m-d'))->first();
        if (count($neworder) == 0) {
            $neworder = new Order();
            $neworder->table_id = Session::get('table_id');
            $neworder->checked_in = $oldorder->checked_out;
            $neworder->user_id = Auth::user()->id;
        }
        $neworder->status = 'Busy';
        $neworder->table->status = 'Busy';
        $neworder->push();
        if ($ids != '')
            $orderDetails = OrderDetail::where('order_id', Session::get('order_id'))->whereIn('id', explode(',', $ids))->get();
        else
            $orderDetails = OrderDetail::where('order_id', Session::get('order_id'))->get();
        foreach ($orderDetails as $orderDetail) {
            $orderDetail->order_id = $neworder->id;
            $orderDetail->save();
        }
        if (count($oldorder->order_details) == 0) {
            $oldorder->table->status = 'Free';
            $oldorder->push();
            $oldorder->delete();
        }
        Session::put('order_id', $neworder->id);
        return view('cashier._order', ['order' => $neworder]);
    }

    public function table()
    {
        return view('cashier.table', ['tables' => Table::orderBy('name')->get()]);

    }

    public function selectTable($id)
    {
        Session::put('table_id', $id);
        $order = Order::where('table_id', Session::get('table_id'))->where('status', '!=', 'Completed')->where('status', '!=', 'Moved')->where(DB::raw('date(created_at)'), date('Y-m-d'))->first();
        if (count($order) > 0)
            Session::put('order_id', $order->id);
        else {
            Session::put('order_id', '');
            $order = [];
        }
        return view('cashier._order', ['order' => $order]);
    }

    public function changeTable()
    {
        Session::put('selected_items', Input::get('ids'));
        return view('cashier.change_table', ['tables' => Table::where('id', '!=', Session::get('table_id'))->orderBy('name')->get()]);
    }

    public function delete($id)
    {
        $order_detail = OrderDetail::find($id);
//        if ($order_detail->product_id != 0) {
        $order_detail->user_id = Auth::user()->id;
        $order_detail->save();
        $order_detail->delete();
//        }
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }

    public function open(Request $request)
    {
        if ($request->isMethod('get'))
            return view('cashier.open');
        else {
            $validator = Validator::make(Input::all(), [
                "description" => "required",
                "quantity" => "required|numeric",
                "price" => "required|numeric",
            ]);
            if ($validator->fails()) {
                return array(
                    'fail' => true,
                    'errors' => $validator->getMessageBag()->toArray()
                );
            }
            $order = Order::find(Session::get('order_id'));
            if (count($order) == 0) {
                $order = new Order();
                $order->table_id = Session::get('table_id');
                $order->checked_in = date('Y-m-d H:i:s');
                $order->user_id = Auth::user()->id;
            }
            $order->status = 'Busy';
            $order->table->status = 'Busy';
            $order->push();
            $orderDetail = new OrderDetail();
            $orderDetail->order_id = $order->id;
            $orderDetail->ordered_date = $order->created_at;
            $orderDetail->description = Input::get('description');
            $orderDetail->quantity = Input::get('quantity');
            $orderDetail->price = Input::get('price');
            $orderDetail->user_id = Auth::user()->id;
            $orderDetail->save();
            Session::put('order_id', $order->id);
            return view('cashier._order', ['order' => $order]);
        }
    }

    public function returnOrder()
    {
        return view('cashier._order', ['order' => []]);
    }

    public function printPayment()
    {
        DB::beginTransaction();
        try {
            $order = Order::find(Session::get('order_id'));
            $order->status = 'Completed';
            $order->usd = Session::get('usd');
            $order->table->status = 'Free';
            $order->push();
            foreach ($order->order_details()->whereNotNull('product_id')->get() as $order_detail) {
                $recipes = Recipe::where('product_id', $order_detail->product_id)->get();
                foreach ($recipes as $recipe) {
                    $item = Item::find($recipe->item_id);
                    $item->quantity -= ($recipe->quantity * $order_detail->quantity);
                    $item->save();
                }
            }
            DB::commit();
            Session::put('order_id', '');
        } catch (\Exception $ex) {
            DB::rollback();
            return view('cashier._order', ['order' => $order, 'pay_error' => 1]);
        }
        return view('cashier.print_payment', ['order' => $order]);
    }

    public function pay(Request $request)
    {
        if ($request->isMethod('get')) {
            $order = Order::find(Session::get('order_id'));
            return view('cashier.pay', ['order' => $order]);
        } else {
            $validator = Validator::make(Input::all(), [
                "usd" => "numeric"
            ]);
            if ($validator->fails()) {
                return array(
                    'fail' => true,
                    'errors' => $validator->getMessageBag()->toArray()
                );
            }
            $order = Order::find(Session::get('order_id'));
            $total = $order->order_details()->select(DB::raw('sum(quantity*price*(1-discount/100)) as  total'))->first()->total;
            $total = $total * (1 - $order->discount / 100);
            $cashin = Input::get('usd');
            if ($total > $cashin)
                return array(
                    'fail' => true,
                    'errors' => ['usd' => 'The cash must be equal or higher than total price!']);
            Session::put('usd', Input::get('usd'));
            $change = $cashin - $total;
            Session::put('change_us', $change);
        }
    }

    public function getPrint()
    {
        $order = Order::find(Session::get('order_id'));
        $order->status = 'Printed';
        $order->checked_out = date('Y-m-d H:i:s');
        $order->table->status = 'Printed';
        $order->push();
        return View('cashier.print', ['order' => $order]);
    }

    public function reloadOrder()
    {
        return view('cashier._order', ['order' => Order::find(Session::get('order_id'))]);
    }
}

 

Step 4: How to Test?

Please login as Cashier user (user who has Cashier role), then you will see the cashier screen as below. 

sale-operation-cashier

select-table

invoice

Hope you can do it.


Demo


Related Posts

© 2018 All Rights Reserved.