Laravel calculate total balance - laravel

Here is my Table:
| id | type | balance
| ----|--------| -------
| 1 | credit | 2400
| 2 | credit | 4800
| 3 | debit | 1200
The calculated amount should be 6000. (2400 + 4800 - 1200) = 6000
How can I do this using Eloquent or collection?

Using laravel collection and one sql query.
return Model::all()->reduce(function ($carry, $item) {
return $item->type == 'credit'
? $carry + $item->balance : $carry - $item->balance;
},0);

You can do by this using Eloquent:
Credits
$totalCredits = Model::where('type', 'credit')->sum('balance');
Debits
$totalDebits = Model::where('type', 'debit')->sum('balance');
Balances
$Total = $totalCredits - $totalDebits
If you want SUM only then do this
DB::table("table")->get()->sum("balance")

Related

Is it possible to groupBy (month) and sum (each column) in table

+---------+--------+---------+---------+
| date | type_a | type_b | type_zzz|
+---------+--------+---------+---------+
|01-01-18 | 12 | 10 | 1 |
|02-01-18 | 2 | 5 | 1 |
|03-01-18 | 7 | 2 | 2 |
|01-02-18 | 13 | 6 | 55 |
|02-02-18 | 22 | 33 | 5 |
+---------+--------+---------+---------+
Hi,
In above example, I would like to know if it's possible to groupBy month and sum each column when getting results in Laravel (tables are dynamic so there are no models for them and also some tables don't have column 'type_a' other don't have 'type_zzz' etc...).
What I'm looking to get from above table is something like this:
"01" =>
'type_a' : '21',
'type_b' : '17',
'type_zzz': '4'
"02" =>
'type_a' : '35',
'type_b' : '39',
'type_zzz': '60'
I'm using following code to group it by month but I'm not able to find solution to return sum by each column:
DB::table($id)->get()->groupBy(function($date) {
return Carbon::parse($date->repdate)->format('m');;
});
If I understand your question correctly, you can either group and sum the values using an SQL query:
$grouped = DB::table('table_name')
->selectRaw('
SUM(type_a) AS type_a,
SUM(type_b) AS type_b,
SUM(type_z) AS type_z
')
->groupByRaw('MONTH(date)')
->get();
Or if you don't want to have to specify the column names in each query, you can use groupBy, array_column, and array_sum on your collection:
$grouped = DB::table('table_name')
->get()
->groupBy(function ($item) {
return Carbon::parse($item->date)->format('m');
})
->map(function ($group) {
$group = $group->toArray();
$summed = [];
$columns = array_keys($group[0]);
array_shift($columns);
foreach ($columns as $column) {
$summed[$column] = array_sum(array_column($group, $column));
}
return $summed;
});

Laravel: Merge two query builders

I have a table of courses which will be free to access or an admin will need to click something to let users see the course.
The course table looks like this:
| id | title | invite_only |
|----|----------------|-------------|
| 1 | free course | 0 |
| 2 | private course | 1 |
Separate from this I have a course_user table, where initially users request access, then admins can approve or deny access:
| id | user_id | course_id | approved | declined |
|----|---------|-----------|----------|----------|
| 1 | 3 | 2 | 1 | 0 |
| 2 | 4 | 1 | 0 | 1 |
| 3 | 4 | 2 | 0 | 0 |
I'd like to index all the courses a user has access to:
class User extends model{
public function myCourses(){
$public = $this->publicCourses;
$invited = $this->invitedCourses;
return $public->merge($invited);
}
public function publicCourses(){
return $this
->hasMany('App\Course')
->where('invite_only', false);
}
public function invitedCourses(){
return $this
->belongsToMany("\App\Course")
->using('App\CourseUser')
->wherePivot('approved', 1);
}
}
How can I make the myCourses function return the results of both publicCourses and invitedCourses by doing only one database query? I'd like to merge the two query builder instances.
According to the doc, you can use union to merge query builders. But as far as I know, it does not work with relations. So maybe you should do it from within controller instead of model. This is an example based on what I understand from your example:
$q1 = App\Course::join('course_user', 'course_user.course_id', 'courses.id')
->join('users', 'users.id', 'course_user.user_id')
->where('courses.invite_only', 0)
->select('courses.*');
$q2 = App\Course::join('course_user', 'course_user.course_id', 'courses.id')
->join('users', 'users.id', 'course_user.user_id')
->where('courses.invite_only', 1)
->where('course_user.approvoed', 1)
->select('courses.*');
$myCourses = $q1->unionAll($q2)->get();
You can also refactor the code further by creating a join scope in App\Course.
I was able to make a much simpler query, and use Laravel's orWherePivot to extract the correct courses:
public function enrolledCourses()
{
return $this
->courses()
->where('invitation_only', false)
->orWherePivot('approved', true);
}

How can I filter a query using laravel relationships

I have a table of items that contain info of the items. Plus, I have 3 other tables for some characteristics that could have more than one.
Follows an example:
table items
-----------------------
| id | price | stock |
-----------------------
| 1 | 19 | 99 |
-----------------------
table tallas
-----------------------------
| id | item_id| description |
-----------------------------
| 1 | 1 | large |
-----------------------------
table colors
-----------------------------
| id | item_id| description |
-----------------------------
| 1 | 1 | blue |
-----------------------------
table materials
-----------------------------
| id | item_id| description |
-----------------------------
| 1 | 1 | cotton |
-----------------------------
I want to know if there is a way where I can filter an item passing the item_id to the tallas relationship without using join (for example).
My model looks like this:
<?php
class Item extends Eloquent{
use Conner\Tagging\TaggableTrait;
public function tallas()
{
return $this->hasMany('Talla','item_id');
}
public function colores()
{
return $this->hasMany('Color','item_id');
}
public function materiales()
{
return $this->hasMany('Material','item_id');
}
public function imagenes()
{
return $this->hasMany('ItemImage','item_id');
}
}
And I have tried this:
$items = Item::with('imagenes')
->with(array('tallas' => function($query) use($dataFilter) {
$query->where('id','=',$dataFilter['filter-size']);
}));
But this return all the items and filter the tallas , using the example tables if i look for an item small it will return something like this.
[item]{
id:1,
price:19,
stock:99,
tallas:
[]...
colores:
[]...
materiales:
[]...
}
It should not return any item, any help?
EDITED
i forget to mention i'm using laravel 4.2
If I understand you question correctly I think you want whereHas e.g.
$items = Item::with('imagenes')
->whereHas('tallas', function ($query) use ($dataFilter) {
$query->where('id', '=', $dataFilter['filter-size']);
});
https://laravel.com/docs/4.2/eloquent#querying-relations
Hope this helps!

Cakephp 3: belongsToMany contain or matching condition?

Piece of my database looks like database part
Categories use tree behavior.
How can i get a manufacturer's (Producers) Products for current Category?
I tried contain and matching, but i received duplicated data or Producers names without related Products.
EDIT:
$query = $this->Producers->find()->matching('Products.Categories',
function ($q) {
return $q->where(['Categories.id' => 18]);
}
);
Results:
Producent: Canon
-------------------------------------------
| ID | Name | Barcode |
-------------------------------------------
| 1 | EOS 1000D | |
-------------------------------------------
| 18 | Camera | |
-------------------------------------------
| 23 | 18 | |
-------------------------------------------
First row (id = 1) it's what i need.
Now i have to remove from results:
second row (id = 18) this is Category id from table Categories,
thrid row (id = 23) - from Products_Categories table.
Done. There is working query:
$query = $this->Producers->find()
->select(['Producers.id','Producers.name', 'Products.id', 'Products.name'])
->matching(
'Products.Categories', function ($q) use ($categoryId){
return $q->where(['Categories.id' => $categoryId]);
}
);

Calculating the sum of diffrent columns in TableView

I have a Table Witch look like the below table
TableVeiw<Transaction>
---------------------------------------------------------------------
| id | Transaction date | Name | type | Debit Amount | Credit Amount|
|---------------------------------------------------------------------|
| 1 | 21/02/2016 |Invoice|Credit | | 12000 |
|---------------------------------------------------------------------|
| 2 | 21/02/2016 |Payment|Debit | 20000 | |
|---------------------------------------------------------------------|
| Total Debit | Total Credit |
-----------------------------
The data in Debit amount and Credit amount come from one property of Transaction Object the code snnipet of how to populate those columns is below:
tcCreditAmmout.setCellValueFactory(cellData -> {
Transaction transaction = cellData.getValue() ;
BigDecimal value = null;
if(transaction.getKindOfTransaction() == KindOfTransaction.CREDIT){
value = transaction.getAmountOfTransaction();
}
return new ReadOnlyObjectWrapper<BigDecimal>(value);
});
tcDebitAmmout.setCellValueFactory(cellData -> {
Transaction transaction = cellData.getValue() ;
BigDecimal value = null;
if(transaction.getKindOfTransaction() == KindOfTransaction.DEBIT){
value = transaction.getAmountOfTransaction();
}
return new ReadOnlyObjectWrapper<BigDecimal>(value);
});
I need to calculate the total of :Total Debit(See the above table) and Total Credit (See the above table) every time the TableView item changes via Javafx Bindings, but i have no idea how to acheive this.
Note: Total Debit and Total Credit are Labels ,
Assuming you have
TableView<Transaction> table = ... ;
Label totalDebit = ... ;
Label totalCredit = ... ;
then you just need:
totalDebit.textProperty().bind(Bindings.createObjectBinding(() ->
table.getItems().stream()
.filter(transaction -> transaction.getKindOfTransaction() == KindOfTransaction.DEBIT)
.map(Transaction::getAmountOfTransaction)
.reduce(BigDecimal.ZERO, BigDecimal::add),
table.getItems())
.asString("%.3f"));
and of course
totalCredit.textProperty().bind(Bindings.createObjectBinding(() ->
table.getItems().stream()
.filter(transaction -> transaction.getKindOfTransaction() == KindOfTransaction.CREDIT)
.map(Transaction::getAmountOfTransaction)
.reduce(BigDecimal.ZERO, BigDecimal::add),
table.getItems())
.asString("%.3f"));
If getAmountOfTransaction might change while the transaction is part of the table, then your table's items list must be constructed with an extractor.

Resources