I am really new to laravel and quite new to codding. I am surprise that running totals or balances don't receive a lot of attention.
The problem is:
I have the current balance of an account recorded in the database.
I have a page called account/$id, where I get all the transactions of the account with that id.
My last column is the balance of the account id after that transaction. A reverse running total, I think it is called. Example: balance of transaction 3 = balance of transaction 2 - ammount of transaction 2.
Until here everything works.
However, when I enter paginate; only the first page give me the correct balance. In the second the balance restarts from the begining.
Code that works:
Controller
$transactions=\App\Transaction::orderByDesc('transaction_date')->orderByDesc('created_at')->where('account_id',$id)->get();
$previousTransaction=0;
$previousBalance=$account->account_current_balance;
foreach ($transactions as $key => $transaction) {
$balances[]=$previousBalance-$previousTransaction;
$previousBalance=array_values($balances)[++$key-1];
$previousTransaction = $transaction->transaction_ammount;
}
View
#foreach($transactions as $key => $transaction)
<td class="align">{{array_values($balances)[++$key-1]}}</td>
#endforeach
Code that doesn't give me the correct balance:
Controller
$transactions=\App\Transaction::orderByDesc('transaction_date')->orderByDesc('created_at')->where('account_id',$id)->paginate(20);
$previousTransaction=0;
$previousBalance=$account->account_current_balance;
foreach ($transactions as $key => $transaction) {
$balances[]=$previousBalance-$previousTransaction;
$previousBalance=array_values($balances)[++$key-1];
$previousTransaction = $transaction->transaction_ammount;
}
View
#foreach($transactions as $key => $transaction)
<td class="align">{{array_values($balances)[++$key-1]}}</td>
#endforeach
<div class="content-header noevents">
{{ $transactions->links() }}
</div>
I have tryed as well different appends in links(), but it seems that I don't know how to use it or doesn't work.
Really big thanks in advance to anyone that can help me.
problem :
every time you navigate through pagination links, you actually send a get request to the same URL, plus ?page=N (N: link number) E.g.
https://example.com/account/36?page=2.
and each time controller should execute, and at the beginning, it set
$previousTransaction=0;
$previousBalance=$account->account_current_balance;
solution:
I don't have your complete code, but your controller should be something like this:
public function ControllerFunction(Request $request){
$transactions=\App\Transaction::orderByDesc('transaction_date')->orderByDesc('created_at')->where('account_id',$id)->paginate(20);
if(!$request->has(['pre_trans', 'pre_balance']){
$previousTransaction=0;
$previousBalance=$account->account_current_balance;
}else{
$previousTransaction = $request['pre_trans'];
$previousBalance = $request['pre_balance'];
}
foreach($transactions as $key => $transaction) {
$balances[]=$previousBalance-$previousTransaction;
$previousBalance=array_values($balances)[++$key-1];
$previousTransaction = $transaction->transaction_ammount;
}
if(!$request->has(['pre_trans', 'pre_balance']){
$request->request->add(['pre_trans' => $previousTransaction]);
$request->request->add(['pre_balance' => $previousBalance]);
}else{
$request['pre_trans'] = $previousTransaction;
$request['pre_balance'] = $previousBalance;
}
}
Related
[UPDATE]
I'm studying number sum at laravel.
I would like to calculate table's columns total amount every month.
I wrote below code and I got this dd result (image)
public function count()
{
Contact::whereYear('created_at', 2021)
->orderBy('created_at')
->get()
->groupBy(function ($row) {
return $row->created_at->format('m');
})
->map(function ($day) {
// dd($day);
return $day->sum('q1a');
});
}
However I only get white blank page at my blade file.
My blade file(count.blade.php) is like this
<h3>{{ $q1a }}</h3>
Could you teach me correct code please?
And one thing When I try to sum I got this error
Warning: A non-numeric value encountered
some of column are not number so I would like to adjust
fix controller code.
WEB.php
//calc total amount page
Route::get('count', 'ContactsController#count');
[UPDATE]
I wrote below code using Dear OMR's answer
public function count()
{
Contact::whereYear('created_at', 2021)
->orderBy('created_at')
->select(['id','sno','s_date', DB::raw("MonthName(created_at)as monthName"), DB::raw('sum(q1a)')])
->groupBy(['id','sno','s_date', 'monthName', 'q1a'])->get();
}
count.blade.php code is below
#foreach ($values as $value)
{{ $value->sumQ }}
#endforeach
Here is current dd result
you can do it in DB stage, witch would be faster:
$values= Contact::whereYear('created_at', 2021)
->orderBy('created_at')
->select(['id','sno','s_date', DB::raw("MonthName(created_at)as monthName"), DB::raw('sum(q1a) as sumQ ')])
->groupBy(['id','sno','s_date', 'monthName'])->get();
note: any column you add it to select statement, should be also added in group by statement.
This question already has answers here:
Laravel sorting last record
(5 answers)
Closed 2 years ago.
I'm trying to minimize the amount of queries I'm using by "eager loading" a threads' replies pagination. But I'm a little unsure how to do it. Below is the code:
$unpinnedThreads = Thread::all()->sortByDesc(function($thread) {
$replies = $thread->replies->sortByDesc('created_at');
$lastTouchedPost = Carbon::minValue();
if (!empty($replies->toArray())) {
$lastTouchedPost = $lastTouchedPost->max($replies->first()->created_at);
}
return $lastTouchedPost->max($thread->created_at);
});
View:
#foreach($thread->replies->paginate(15)->setPath($thread->path())->getUrlRange(ceil($thread->replies->count()
/ 15 - 2), ceil($thread->replies->count() / 15)) as $key => $pagination)
#if($key > 1)
{{ $key }}
#endif
#endforeach
So far I have alot of queries in the debug bar that looks like this:
select * from `replies` where `replies`.`thread_id` = ? and `replies`.`thread_id` is not null
I was wondering how I could reduce the number of queries.
When I code: Thread::with('replies')->sortByDesc->, it throws calls to undefined method. However when I code ->with('replies'), it throws an error that says:
Method Illuminate\Database\Eloquent\Collection::with does not exist.
Can anyone please help me?
Thank you.
Edit::
I've deduced the issue is in my method:
$unpinnedThreads = Thread::all()->sortByDesc(function($thread) {
$replies = $thread->replies->sortByDesc('created_at');
$lastTouchedPost = Carbon::minValue();
if (!empty($replies->toArray())) {
$lastTouchedPost = $lastTouchedPost->max($replies->first()->created_at);
}
return $lastTouchedPost->max($thread->created_at);
});
Does anyone know how I can optimize the method?
Answer found here: Laravel sorting last record
"One solution I would suggest is to have the replied touch the topics. https://laravel.com/docs/5.3/eloquent-relationships#touching-parent-timestamps
This way you can always order by the Topic's updated_at because whenever a reply is created/edited it will update the Topic as well.
To achieve this you would just need to add:
protected $touches = ['topic'];
The above is assuming that the method name for the topics relationship in the replies model is topic().
Hope this helps!"
That is really strange. It appears that you are calling with() in the model Thread::with('replies'), but the error is saying that you are calling it on a collection. The collection object does not have the with() method.
The bellow code should work:
$collection = Thread::with(['replies'])->get()->sortByDesc(function($thread)
{
if (count($thread->replies))
{
return $thread->replies->sortBy('created_at')->last()->created_at;
}
else
{
return $thread->created_at;
}
});
If you are not using the defaults, created_at must be configured:
protected $casts = [
'created_at' => 'date',
]
Don't forget to create the relationship inside your Thread model:
public function replies()
{
return $this->hasMany(Reply::class, 'thread_id', 'id');
}
I've been scratching my head over this since last night. I have this function on my controller:
public function generate_documents($id)
{
$contract = Contract::find($id);
$booking_ids = $contract->booking_id;
$booking_ids = json_decode($booking_ids);
$bookings = Booking::find($booking_ids);
}
$booking_ids returns a json of ids that are stored in the database. I then find the booking records based on the IDs.
foreach($bookings as $booking) {
$asset = Omg_asset::where('id', $booking->omg_asset)->first();
}
Here's the part where I am expecting 3 results but only the last one gets returned on my view. I tried this method:
$asset = '';
foreach($bookings as $booking) {
$asset .= Omg_asset::where('id', $booking->omg_asset)->first();
}
But whenever I try to retrieve the values on my view, it's returning a json containing all the records I need and I can't access it via index.
Attaching a screenshot for better context:
Here's my code on my view by the way:
#foreach($bookings as $booking)
<tr>
<td>{{ $asset }}</td>
</tr>
#endforeach
Here's the error thrown whenever I try to do {{ $asset['asset_name'] }} on view:
"Illegal string offset 'asset_name'"
I haven't used Laravel in a long time so I would really appreciate your help. If there's also a better way to do this, I'm open for suggestions.
Thanks in advance!
I want to try to find a solution that it isn't possible to insert same number twice in a table or to turn red in case the number was inserted before.
See also bureautintdev.nl/question/example1
Use Laravels inbuild validator functionality.
$validator = Validator::make(array('phonenumber' => 'required|unique:users') );
// This will query DB for uniqueness of phone number in users table. Change according to your requirement.
//Check for validation
if($validator->fails()) {
$messages = $validator->messages();// get the error message.
return Redirect::to('inputview')->withErrors($validator);
}
else
{
//do your actual operation here.
}
In the "inputview", check for "phonenumber" error and do decorate your inputbox into red or raise alert.
#if ($errors->has('phonenumber')) <p>{{ $errors->first('phonenumber') }}</p> #endif //show error.
I'm using the table class that auto-generates a table for me from an array of data pulled from my database.
Model:
function get_reports_by_user_id($userid)
{
return $this->db->get_where('ss2_report',array('userid' => $userid))->result_array();
}
Controller:
function index()
{
echo $this->table->generate($this->mymodel->get_reports_by_user_id('1234'));
}
The controller will eventually be moved to a view when I have it working. This generates the table just fine, but I'd like to add a link to a field. For example, the id column that would allow me to link to a page of data for just that report's id. I know I can just output the table the old fashioned way by hand. I can then add whatever links I want, but I'd love to be able to use the auto-generation as much as possible. There's got to be a way to do something as common as linking a table cell. Does anyone have any ideas?
EDIT:
User Java PHP has it mostly right below. Here's the code that makes it work:
function get_reports_by_user_id($userid)
{
$rows = $this->db->get_where('ss2_report',array('userid' => $userid))->result_array();
foreach ($rows as $count => $row)
{
$rows[$count]['id'] = anchor('report/'.$row['id'],$row['id']);
}
return $rows;
}
I just needed to replace the value in the original array with the anchor text version.
The only way is, in the function get_reports_by_user_id() , you would loop through all the results and add the <a href> tag to the ids. Something like this:
function get_reports_by_user_id($userid)
{
$rows=$this->db->get_where('ss2_report',array('userid' => $userid))->result_array();
foreach ($rows as $row)
{
$row->id=anchor('site.com/some_controller/some_function/'.$row->id,$row->id);
}
return $rows;
}
I don't use CodeIgniter's database library so I'm not sure of what format it returns $rows in, but the code above should give you the general idea of what you need to do.
One idea might be to do something like..
foreach ($row in $this->mymodel->get_reports_by_user_id('1234'))
{
$row->id = anchor(site_url(array('report', 'user', $row->id)), $row->id);
$this->table->add_row($row);
}
$this->table->generate();