Laravel Aggregates query not working according to group by - laravel

On POS when I place any order it stored the order detail according to the product id on order_details table. I want to sum the quantity order according to product id.
Order Detail table : id, order_id, product_id, total, created_at, updated_at
Product Controller :
public function index()
{
$orderdetail = DB::table('order_details')
->select('quantity', DB::raw('sum(quantity) as sum'))
->groupBy('product_id')
->havingRaw('SUM(quantity)')
->get();
$products = Product::latest()->with('category', 'supplier', 'orderdetail')->get();
return view('admin.product.index', compact('products', 'orderdetail'));
}
On Product Model:
class Product extends Model
{
protected $dates = [
'buying_date', 'expire_date',
];
public function category()
{
return $this->belongsTo(Category::class);
}
public function supplier()
{
return $this->belongsTo(Supplier::class);
}
public function orderdetail()
{
return $this->belongsTo('App\OrderDetail', 'id', 'product_id');
}
}
}
But it does not show anything on Blade.
on Blade :
#foreach($products as $key => $product)
<tr>
<td>{{ $key + 1 }}</td>
<td>{{ $product->name }}</td>
<td>
<img class="img-rounded" style="height:35px; width: 35px;" src="{{ URL::asset("storage/product/".$product->image) }}" alt="{{ $product->name }}">
</td>
<td>{{ $product->category->name }}</td>
<td>{{ $product->supplier->name }}</td>
<td>{{ $product->code }}</td>
<td>{{ $product->buying_date->toFormattedDateString() }}</td>
<td>{{ number_format($product->buying_price, 2) }}</td>
<td>{{ number_format($product->selling_price, 2) }}</td>
<td>{{ $product->product_unit }}</td>
<td>{{ $product->product_unit - $product->sum }}</td>
<td>{{ $product->sum }}</td>
<td>DLT</td>
</tr>
#endforeach
This is the result of dd on $products and $orderdetail
It aggregates the value not showing the blade template. how I show it on the blade or there any problem on model or blade? please help.

Here I solved via this way
on Controller
public function index()
{
$orderdetail = DB::table('order_details')
->select('quantity', DB::raw('sum(quantity) as soldunit'))
->groupBy('product_id')
->get();
$products = Product::latest()->with('category', 'supplier', 'orderdetail')->get();
return view('admin.product.index', compact('products', 'orderdetail'));
}
and on Model, I have slightly Changed
public function orderdetail()
{
return $this->hasMany('App\OrderDetail','product_id', 'id')->selectRaw('order_details.*,sum(quantity) as soldunit')->groupBy('product_id');
}
after this, to access soldunit on the blade I used this one
{{ $product->orderdetail->sum('soldunit') }}

If you want to access sum of a column via a defined relationship, you need to add it during your main query:
$products = Product::with('category', 'supplier')->with(['orderdetail' => function($query){
$query->select('id', 'product_id', 'quantity', DB::raw('sum(quantity) as sum'));
}])->get();

Related

Value correlation from multiple tables in laravel

I have two tables. One employees and one timesheets
I would like to have correct name at the result but different ID. If you see the result I have the same name everywhere.
How can make the code to fixed my challenge?
Thank you.
In controller I have this code
$profile = ['no' => Auth::user()->no];
$timesheets = Timesheet::where($profile)->select('*')->orderBy('created_at','DESC')->get();
foreach ($timesheets as $employee) {
$emp = ['identification' => $employee->identification];
$oneemployee = Employees::where($emp)->select('*')->orderBy('created_at','DESC')->get();
}
return view('contractor.employees.timesheets', compact('timesheets', 'oneemployee'));
and in blade I have
#foreach ($timesheets as $row1)
<tr>
<td>#</td>
#foreach ($oneemployee as $row2)
<td>{{ $row2->fname}}</td>
<td>{{ $row2->lname}}</td>
#endforeach
<td>{{ $row1->identification}}</td>
<td>{{ $row1->week}}</td>
<td>{{ $row1->year}}</td>
</tr>
#endforeach
According to your commit, I suggest the following solution
If you want dispay timesheet with employees you can use eager loading.
For example:
In your controller:
$profile = ['no' => Auth::user()->no];
$timesheets = Timesheet::where($profile)->with("employees")->select('*')->orderBy('created_at','DESC')->get();
return view('contractor.employees.timesheets', compact('timesheets'));
In your Timesheet model add hasOne relation to Employee:
public function employee(){
return $this->hasOne(Employee::class,'identification','identification')
}
And your view:
#foreach ($timesheets as $timesheet)
<tr>
<td>#</td>
<td>{{ $timesheet->employee->fname}}</td>
<td>{{ $timesheet->employee->lname}}</td>
<td>{{ $timesheet->identification}}</td>
<td>{{ $timesheet->week}}</td>
<td>{{ $timesheet->year}}</td>
</tr>
#endforeach

How to calculate using data from get() in controller

I have some data from a table and I'm doing an eloquent get for it. So far from what I know is when using get(), I need to loop it first using foreach to get the data.
My question is how to move my logic code to controller? so I just need to pass it to view. Because I'm doing it on blade directly
Bellow is my controller, I'm just simply get a data from database:
$attendances = Attendance::where('company_id', Auth::user()->company_id)->get();
#foreach ($attendances as $attendance)
// How to move this php code to my controller?
#php
$work_hour_start = $attendance->work_hour_start;
$attendance_time = \Carbon\Carbon::parse($attendance->attendance_time)->format('H:i:s');
$tolerance = \Carbon\Carbon::parse($attendance_time)->addMinutes($attendance->late_tolerance);
if ($tolerance > $work_hour_start) {
$is_late = 'Late';
} else {
$is_late = 'On Time';
}
#endphp
<tr>
<td>{{ $attendance->employee->name }}</td>
<td>{{ Carbon\Carbon::parse($attendance->attendance_time)->format('H:i:s') }}</td>
<td>{{ $attendance->location_library->location_name }}</td>
<td>{{ $is_late }}</td>
</tr>
#endforeach
I want my blade to be clean, but I don't know how to do that.
You could add attendance_time to the $casts property and make tolerance/is_late accessors in the Attendance Model
# Attendance.php
class Attendance extends Model
{
...
protected $casts = [
'attendance_time' => 'datetime',
];
...
public function getToleranceAttribute()
{
return $this->attendance_time->addMinutes($this->late_tolerance);
}
public function getIsLateAttribute()
{
return $this->tolerance > $this->work_hour_start
? 'Late'
: 'On time';
}
...
}
#foreach ($attendances as $attendance)
<tr>
<td>{{ $attendance->employee->name }}</td>
<td>{{ $attendance->attendance_time->format('H:i:s') }}</td>
<td>{{ $attendance->location_library->location_name }}</td>
<td>{{ $attendance->is_late }}</td>
</tr>
#endforeach
Just do it, move the logic to your controller and set it up in your $attendances collection. Something like this:
$attendances = Attendance::where('company_id', Auth::user()->company_id)->get();
foreach ($attendances as $key => $attendance){
$attendances[$key]->attendance_time = \Carbon\Carbon::parse($attendance->attendance_time)->format('H:i:s');
if (\Carbon\Carbon::parse($attendances[$key]->attendance_time)->addMinutes($attendance->late_tolerance > $attendance->work_hour_start) {
$attendances[$key]->setAttribute('is_late', 'Late');
} else {
$attendances[$key]->setAttribute('is_late', 'On Time');
}
}
return view('your-view', ['attendances' => $attendances]);
Now it will be able to iterate on your template:
#foreach ($attendances as $attendance)
<tr>
<td>{{ $attendance->employee->name }}</td>
<td>{{ $attendance->attendance_time }}</td>
<td>{{ $attendance->location_library->location_name }}</td>
<td>{{ $attendance->is_late }}</td>
</tr>
#endforeach

Eloquent 3 tables relationship in Vue component

I have got this relationships:
CUSTOMER
id
name
ADDRESS
id
name
customer_id
country_id
COUNTRY
id
name
My Customer model:
class Customer extends Model
{
use SoftDeletes;
public function addresses()
{
return $this->hasMany(Address::class);
}
My address model:
class Address extends Model
{
use SoftDeletes;
public function country()
{
return $this->hasOne(Country::class);
}
And right now doing:
Customer::with('addresses')->orderBy('id', 'DESC')
I can get all customer with his addresses. But How Can I get the name of country fro customer?
I know getting in blade, if I do 2 loops I can create $address variable and get country names:
loop customers
loop adddresses
$address->name
$address->country (name of country)
But if I try in Vue:
<tr v-for="(customer, index) in customers" :key="customer.id">
<td>{{ customer.id}}</td>
<td>{{ customer.firstname}}</td>
<td>{{ customer.lastname}}</td>
<td v-if="customer.addresses">
<tr v-for="(address, index) in customer.addresses" :key="address.id">
<td>{{ address.name }}</td>
<td>{{ address.country }}</td>
</tr>
</td>
I dont get any value in addres.country. I mean, how Can I relate CUSTOMERS & COUNTRIES for usign in Vuejs?
Thans in advance
I found a solution!
I updated Address model like this:
class Address extends Model
{
public function country()
{
return $this->belongsTo(Country::class);
}
protected $with = ['country'];
}
then I can solve country name like this:
<tr v-for="(customer, index) in customers" :key="customer.id">
<td>{{ customer.id}}</td>
<td>{{ customer.name}}</td>
<td v-if="customer.addresses">
<tr v-for="(address, index) in customer.addresses" :key="address.id">
<td>{{ address.name }}</td>
<td>{{ address.country.name }}</td>
</tr>
</td>

Can't display mongodb collection to view Laravel

I'm using MongoDb and Laravel for a demo.
I'm trying to get the collection from MongoDb and display it to view in Laravel.
Here is my model:
class Account extends Eloquent
{
public function getAllAccount() {
$account = DB::connection('mongodb')->collection('Account')->get();
return $account;
}
}
Here is my Controller:
class AccountController extends Controller
{
public function index() {
$acc = new Account();
$data = $acc -> getAllAccount();
return view('account', $data);
}
}
And then, I display it to view:
#if(isset($data))
#foreach($data as $dataValue)
<tr>
<td>{{ $dataValue->_id }}</td>
<td>{{ $dataValue->avail_balance }}</td>
<td>{{ $dataValue->last_activity_date }}</td>
<td>{{ $dataValue->open_date }}</td>
<td>{{ $dataValue->pending_balance }}</td>
<td>{{ $dataValue->cust_id }}</td>
<td>{{ $dataValue->open_branch_id }}</td>
<td>{{ $dataValue->open_emp_id }}</td>
<td>{{ $dataValue->product_id }}</td>
</tr>
#endforeach
#endif
I set Controller in web.php:
Route::get('/account', 'AccountController#index');
But when I run this, it return nothing, just a blank page.
How I can fix that?
Thank you very much!
UPDATE:
I use dd($data) in my controller and here is all my collection:
You've got to send the data back in a format the page can take.
In the index() method, change:
return view('account', $data);
to
return view('account', compact ('data');
To be pretty, you can use ->with() as well, but I like compact since you can move a lot of variables easily.

Laravel need data from two different collections in for each

I have a for each loop to iterate over the collection of records. It has the user_id, but not the other user credentials. I created another collection of user. How do I include this in my iteration?
Controller
public function index(Request $request, $id)
{
$thoughts = Thought::where('id', $id)->orderBy('created_at', 'desc')->paginate(100)->get();
$user = User::where('id', $thoughts->user_id);
return view('backend.pages.thought_list', compact('thoughts, user'));
}
View
#foreach ($thoughts as $thought)
<tr>
<td class="col-md-1">{{ $user->username}} <span class="user_id_thought">ID - {{ $user->user_id}}</span></td>
<td class="col-md-1">{{ $thought->response }}</td>
<td>{{ $thought->thought_type }}</td>
<td>{{ $thought->id }}</td>
</tr>
#endforeach
How do I display my users variable in the loop. Or is there a better way of doing this.
Eager Loading is the perfect use case for your requirement in my opinion.
e.g.
$thoughts = Thought::with('user')->get();
foreach ($thoughts as $thought) {
echo $thought->user->name;
}
For more details see: https://laravel.com/docs/5.6/eloquent-relationships#eager-loading

Resources