Laravel 8: Convert array to same format of the model - php

In view, there's 2 tables and implemented the pagination for both but having a problem in the buttons
When we tried to change the page of table 1, the table 2 is also changed
In the controller, there's 4 model: 1) Purchase; 2) Direct Payments; 3) Sales; 4) Direct Collections.
purchases columns
id
number,
date_delivered
direct payments columns
id,
number
date
After getting the data from the perspective model we, rearrange the format
**Rearrange the format **
public function setToInputOutputTax($data,$module,$module_id)
{
$items = [];
foreach($data as $d => $datum) {
$items[] = [
'id' => $datum->id,
'checkbox' => 0,
// 'vat_type' => $vat_type,
'transaction_date' => isset($datum->date_delivered) ? $datum->date_delivered : $datum->date,
'transaction_number' => $module . $datum->number,
'module_id' => $module_id,
'vat_id' => $datum->vat->id,
'vat_code' => $datum->vat->code.' - '.$datum->vat->name,
'vat_rate' => $datum->vat_rate,
'net_of_vat' => $datum->net_of_vat,
'amount_due' => $datum->amount_due,
'balance' => $datum->vat_balance,
'amount_to_apply' => $datum->vat_balance,
];
}
return $items;
}
We merged the purchase & direct payments, same goes with sale & direct collection
$purchases = Purchase::select(
'id',
'number',
'date_delivered',
'vat_id',
'vat_rate',
'net_of_vat',
'amount_due',
'vat_balance'
)
->where('level_id',4)
->where('vat_balance','>', 0)
->where('company_id',Auth::user()->company_id)
->search(trim($this->input_search))
->orderBy('id', $this->order)
->get();
$purchases_input_tax = $this->setToInputOutputTax($purchases,'P-',201);
$direct_payments = DirectPayment::select(
'id',
'number',
'date',
'vat_id',
'vat_rate',
'net_of_vat',
'amount_due',
'vat_balance'
)
// ->union($purchases)
->where('level_id',4)
->where('vat_balance','>', 0)
->where('company_id',Auth::user()->company_id)
->search(trim($this->input_search))
->orderBy('id', $this->order)
->get();
// ->paginate(10, ['*'], 'input');
$direct_payments_input_tax = $this->setToInputOutputTax($direct_payments,'DP-',210);
$input_tax = array_merge($purchases_input_tax,$direct_payments_input_tax);
$col = collect($input_tax);
$input_currentPage = Paginator::resolveCurrentPage();
$currentPageItems = $col->slice(($input_currentPage - 1) * $this->input_size, $this->input_size)->all();
$all_input_taxes = new Paginator($currentPageItems, count($col), $this->input_size);
$sales = Sale::where('level_id',4)
->where('vat_balance','>', 0)
// ->where('status_id',[3,9])
->where('company_id',Auth::user()->company_id)
->search(trim($this->output_search))
->orderBy('id', $this->order)
->get();
// ->paginate(10, ['*'], 'output');
$sales_output_tax = $this->setToInputOutputTax($sales,'S-',101);
$direct_collections = DirectCollection::where('level_id',4)
->where('vat_balance','>', 0)
->where('company_id',Auth::user()->company_id)
->search(trim($this->output_search))
->orderBy('id', $this->order)
->get();
// ->paginate(10, ['*'], 'output');
$direct_collections_output_tax = $this->setToInputOutputTax($sales,'DC-',110);
$output_tax = array_merge($sales_output_tax,$direct_collections_output_tax);
$output_col = collect($output_tax);
$output_currentPage = Paginator::resolveCurrentPage();
$output_currentPageItems = $output_col->slice(($output_currentPage - 1) * $this->output_size, $this->output_size)->all();
$all_output_taxes = new Paginator($output_currentPageItems, count($output_col), $this->output_size);
Question: Is it possible to convert the array to same format of the model? Reason why we need to do this is because we need to paginate the new format

Related

Laravel Eloquent get Clients which have active jobs

I'm working on a table which should show clients which have active jobs. I've got a page with all clients and this is working. I'm trying to get a query which is conditional on the client having active jobs. So here is what I have in my dataSource function:
public function dataSourcejobs(Request $request) {
$search = $request->query('search', array('value' => '', 'regex' => false));
$draw = $request->query('draw', 0);
$start = $request->query('start', 0);
$length = $request->query('length', 25);
$order = $request->query('order', array(0, 'desc'));
$filter = $search['value'];
$sortColumns = array(
0 => 'id',
1 => 'client',
2 => 'active_jobs',
3 => 'is_enabled',
4 => 'actions'
);
$query = Client::select( 'clients.*' );
if (!empty($filter)) {
$query->where( 'title', 'like', '%'.$filter.'%' );
}
$recordsTotal = $query->count();
$sortColumnName = $sortColumns[$order[0]['column']];
$query->orderBy($sortColumnName, $order[0]['dir'])
->take($length)
->skip($start);
$json = array(
'draw' => $draw,
'recordsTotal' => $recordsTotal,
'recordsFiltered' => $recordsTotal,
'data' => [],
);
$clients = $query->get();
foreach ($clients as $client) {
// Get active jobs for this client.
$jobs = Job::where( 'client_id', $client->id )->where('is_active', 1)->get();
$json['data'][] = [
$client->id,
$client->title,
'<button class="jobs">' . count($jobs) . ' Jobs</button>',
( $client->is_enabled === 1 ) ? 'Yes' : 'No',
'' . config( 'ecl.EDIT' ) . ' ' . config( 'ecl.WORK' ) . ''
];
}
return $json;
}
I've tried to do things like $query = Client::select( 'clients.*' )->count($client->jobs); but this is obviously wrong and errors. I also tried to do this in the loop (by checking the count) but this obvoiusly broke how the pagination works (but did show only clients with active jobs)
I should point out that the function above shown all clients even the ones which have no associated active jobs.
thanks
to get the count along with each client you can use withCount refer to this link https://laravel.com/docs/9.x/eloquent-relationships#counting-related-models
like the following
$query = Client::withCount('jobs');
as for getting the clients who only have jobs you can use whereHas

How to create 2 collections based from an array with 2 count in PHP?

I know this is a basic question and I'm sorry I can't answer, but how can I create 2 collections based from an array with 2 values in Laravel/PHP? Here's my code:
$received_items = ReceiveItems::where('voucher_id', '=', $request->voucher_id)->get();
foreach($received_items as $received_item) {
$product_ids = $received_item->product_id;
foreach($product_ids as $product_item_no => $product_id) {
$products = Product::where('id', '=', $product_id);
$voucher_cost = $products->value('cost');
$qty_addend = $received_item->qty_per_item;
$list = array(
'product_item_no' => $product_item_no + 1,
'product_name' => $products->value('name'),
'size' => $products->value('size'),
'qty_addend' => $qty_addend[$product_item_no],
'voucher_cost' => $voucher_cost,
'ext_cost' => number_format($voucher_cost * $qty_addend[$product_item_no], 2)
);
$list = (object)$list;
$received_item->list = $list;
$data = collect([$list]);
}
}
return $data;
Basically, the $product_ids is the array I want to get and count($product_ids) is returning 2, but it's just creating the collection from the 2nd array value. See screenshot below:
screenshot.png
Any help is much appreciated.
In your $list variable it will only store last product_id data, because you have to take $list as multi-dimensional array.
You have to take $list variable out of the second loop, so it not overwrite data.
Try below code:
$received_items = ReceiveItems::where('voucher_id', '=', $request->voucher_id)->get();
foreach($received_items as $received_item) {
$product_ids = $received_item->product_id;
$list = []; // declare list variable here
foreach($product_ids as $product_item_no => $product_id) {
$products = Product::where('id', '=', $product_id);
$voucher_cost = $products->value('cost');
$qty_addend = $received_item->qty_per_item;
$list[] = array( // make it multi-dimentional array
'product_item_no' => $product_item_no + 1,
'product_name' => $products->value('name'),
'size' => $products->value('size'),
'qty_addend' => $qty_addend[$product_item_no],
'voucher_cost' => $voucher_cost,
'ext_cost' => number_format($voucher_cost * $qty_addend[$product_item_no], 2)
);
}
// take this code out of loop
$list = (object)$list;
$received_item->list = $list;
$data = collect([$list]);
}
return $data;

PHP end() function not getting end Array item and object key in Laravel

In my Laravel project, I've got a job set up which runs and attempts to notify a user based on their threshold and chosen alert metrics. I'm using the php end() method to get the last item in an array and then attempting to get whatever metric the user has chosen.
However, upon dumping the data, this isn't returning the last array item, it's returning every item and I'm not sure why?
When I dump my data, I'm getting this format instead of the last item in the array:
[2021-04-13 13:30:45] production.DEBUG: array (
0 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '2190',
'period_from' => '2021-04-13 00:00:00',
'period_to' => '2021-04-13 13:30:02',
'created_at' => '2021-04-13 13:30:06',
),
1 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '5184',
'period_from' => '2021-04-12 00:00:00',
'period_to' => '2021-04-12 23:57:02',
'created_at' => '2021-04-12 23:57:07',
),
2 =>
(object) array(
'event_category' => 'My Category',
'event_action' => 'My Event',
'event_count' => '3820',
'period_from' => '2021-04-11 00:00:00',
'period_to' => '2021-04-11 23:57:02',
'created_at' => '2021-04-11 23:57:07',
),
)
I should just be seeing the last item, amongst all of my code, the following is of significant value here:
/**
* Notify if data meets threshold & alert rules
*
* #return void
*/
public function notifyAlertThreshold($alerts, $data)
{
$newestDataPart = end($data) ?? null;
// alerts for data source
foreach ($alerts as $key => $alert) {
Log::debug($newestDataPart);
$metric = !isset($newestDataPart->{$alert->metric}) ? $newestDataPart : $newestDataPart->{$alert->metric};
}
}
In context, here's some mode of the code, but the primary question here, is why is my end() method not returning the last item?
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$filters = json_decode($this->report->discovery_filters, true);
$this->reportStatus = 'complete';
$data = [];
foreach ($filters as $findableKey => $findable) {
/*
** If there are datasets on the findable objec, then we assume
** that we can build up a chart or some data structure.
*/
if (isset($findable['datasets'])) {
$pushableDatasets = [];
foreach ($findable['datasets'] as $datasetKey => $dataset) {
// query data
if (isset($dataset['query'])) {
$chartLabel = $findable['name'] ?? 'Untitled Chart';
$this->setDynamicChartOptions($chartLabel);
$additionFromField = $dataset['query']['additionFromField'] ?? '';
$resultData = [];
if ($dataset['query']['prefersConversionCalculation'] == 'yes') {
$totals = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['calculateConversionFromTotals'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$goal = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['calculateConversionByGoal'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$totals = $totals->flatten();
$goal = $goal->flatten();
$totalsGrouped = $this->groupData(
$totals,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
$goalsGrouped = $this->groupData(
$goal,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
$totalsGroupedFlattened = $totalsGrouped->flatten();
$goalsGroupedFlattened = $goalsGrouped->flatten();
$resultData = $this->getStructure($findable, $datasetKey, $goalsGroupedFlattened, $totalsGroupedFlattened);
array_push($pushableDatasets, $resultData);
} else {
$res = DB::table($dataset['query']['table'])
->select($dataset['query']['columns'])
->where($dataset['query']['filterBy'])
->orderBy($dataset['query']['orderBy']['field'], $dataset['query']['orderBy']['direction'])
->get()
->chunk(100);
$res = $res->flatten();
if (isset($dataset['query']['useGrouping']) && $dataset['query']['useGrouping'] == 'yes') {
$results = $this->groupData(
$res,
$dataset['query']['groupBy'],
$dataset['query']['groupByFormat'],
$additionFromField
);
// if we're using an addition function our array is already flattened
if (!empty($additionFromField)) {
$resultData = $results;
} else {
$resultData = $results->flatten();
}
array_push($pushableDatasets, $this->getStructure($findable, $datasetKey, $resultData));
}
}
$dataForAlerts = $resultData;
if ($dataset['query']['prefersConversionCalculation'] == 'yes') {
$dataForAlerts = $dataForAlerts['data'];
}
// alerting
$alerts = $this->getAlertThresholds($dataset['query']['table']);
$this->notifyAlertThreshold($alerts, $dataForAlerts);
}
}
$findable['datasets'] = $pushableDatasets;
}
array_push($data, $findable);
}
// no data or it's empty
if (!isset($data) || empty($data)) {
$this->reportStatus = 'error';
}
// create our report data entry
$this->updateReportData(false, $data);
}

Laravel multiple filter with search

I want to search service providers and products, and filter by location and by service, or by location and by-products. i am using below code` $results = new ClientProfile;
if (request()->has('service-provider')) {
$results = $results->where('jobsc_id', request('service-provider'));
} elseif(request()->has('product')) {
$results = $results->where('product_id', request('product'));
} elseif(request()->has('city')){
$results = $results->where('divsec_id', request('city'));
} else {
$results = ClientProfile::searched();
}
$results = $results->where('profile_state', 'active')->paginate(10)->appends([
'service-provider' => request('service-provider'),
'product' => request('product'),
'city' => request('city'),
]);
return view('results')->with('results', $results);`
although it shows URL as domain.com/results?product=2&city=78 it shows all products without filter by city
You use if elseif therefore it when finding one, in the second also does not come.
use when instead if else
$results = new ClientProfile::when(request()->has('service-provider'), function($q){
$q->where('jobsc_id', request('service-provider'));
})
->when(request()->has('product'), function($q){
$q->where('product_id', request('product'));
})
->when(request()->has('city'), function($q){
$q->where('divsec_id', request('city'));
})
->when(count($request->all()) === 0, function($q){
$q->searched();
})
->where('profile_state', 'active')->paginate(10)->appends([
'service-provider' => request('service-provider'),
'product' => request('product'),
'city' => request('city'),
]);
return view('results')->with('results', $results);`
This code worked for me
$results = ClientProfile::when(request()->has('service-provider'), function($q){
$q->where('jobsc_id', request('service-provider'));
})->when(request()->has('product'), function($q){
$q->where('product_id', request('product'));
})->when(request()->has('city'), function($q){
$q->where('divsec_id', request('city'));
})->when(count(request()->all()) === 0, function($q){
$q->searched();
})->where('profile_state', 'active')->paginate(10)->appends([
'service-provider' => request('service-provider'),
'product' => request('product'),
'city' => request('city'),
]);

Eloquent calculate if I have more results left

I'm building a Products API. I need to return a collection of products and a variable telling me if I have more results starting from the last the answer has just returned me to show or hide a load more button. This is all I have until now:
$query = Product::query();
$query->where('category_id', $request->get('category_id'));
$query->orderBy('order', 'asc')
->orderBy('name', 'asc')
->skip($skip)
->take($take);
And this is how I return it:
return [
'products' => $query->get(['id', 'name', 'front_image', 'back_image', 'slug']),
'has_more' => ????
];
How can I calculate the has_more?
The easiest approach would be to query the database twice:
$query = Product::query()
->where('category_id', $request->get('category_id'))
->orderBy('order', 'asc')
->orderBy('name', 'asc');
$count = $query->count();
$hasMore = $skip + $take < $count;
$models = $query->skip($skip)
->take($take)
->get(['id', 'name', 'front_image', 'back_image', 'slug']);
return [
'products' => $models,
'has_more' => $hasMore
];
You can just get the count of the entire records and then simply do the check for has more like so:
<?php
$query = Product::query()
->where('category_id', $request->get('category_id'));
->orderBy('order', 'asc')
->orderBy('name', 'asc');
$count = $query->count();
return [
'products' => $query->skip($skip)
->take($take)
->get(['id', 'name', 'front_image', 'back_image', 'slug']),
'has_more' => ($hm = ($count - ($take + $skip))) > 0 ? $hm : false
];

Categories