Complex query implying dates - php

I'd like to return the customers from Magento who where created the day before OR who where updated the day before. I tried to play with addFieldToFilter, without any success.
I also tried to manipulate Zend_Db_Select, no success.
So now I'm stuck!
Here are some of my tries :
$customer = Mage::getModel('customer/customer');
$customers = $customer
->getCollection()
->getSelect()
->where("updated_at >= ? AND updated_at <= ?",$this->getFrom(), $this->getTo())
->orWhere("e.created_at >= ? AND e.created_at <= ?", $this->getFrom(), $this->getTo());
Or
->addFieldToFilter(
array(
array('attribute'=>'updated_at', 'gteq'=>$this->getFrom()),
array('attribute'=>'created_at', 'gteq'=>$this->getFrom())
),
'',
'left'
);
Thanks

I'd recommend against directly manipulating the select unless it's absolutely necessary and you know exactly what's going on behind the scenes in your version of Magento.
The following syntax should handle the tricky parts for you
$c = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToFilter(array(
array('attribute'=>'updated_at','from'=>'2010-05-12','to'=>'2010-05-30'),
array('attribute'=>'created_at','from'=>'2010-05-12','to'=>'2010-05-13')
));
var_dump( (string) $c->getSelect());
var_dump(count($c));
all you'll need to do is drop in the date ranges you want.

It is enough to use updated_at as your filter attribute, because it is set to current datetime when a user is created. So by filtering with this field you will get both new users and those who are not new but were updated in the given period. Here's the code to look for users updated or created during the last 24 hours:
$customers = Mage::getModel('customer/customer')->getCollection();
$customers->addAttributeToFilter('updated_at', array('gt' => date("Y-m-d H:i:s", time()-60*60*24)));
foreach($customers as $customer) {
//do sth
}

Thanks to Alan and Silvo, here is what I wrote :
->addAttributeToFilter(array(
array('attribute'=>'updated_at','from'=>$this->getFrom(),'to'=>$this->getTo())
));
Both answers were usefull. Thank you!

Related

How to show data with less than current date in yii?

How do i filter the date which is less than the current date?
Company::model()->with(array(
'Bundles'=>array(
'condition'=>'Bundles.status=1',
'order'=>'payment_date DESC',
),
))->findByPk($company_id);
Currently above code is displaying all data whose status = 1
but i want to show the data whose expiry_date should be less than current date. How can i achieve this?
This is what i have tried so far but NO success.
Company::model()->with(array(
'Bundles'=>array(
'condition'=>'Bundles.expiry_date < date("Y-m-d H:i:s")',
'order'=>'payment_date DESC'
),
))->findByPk($company_id);
You can try something like this.
Company::model()->with(array(
'Bundles'=>array(
'condition'=>'Bundles.expiry_date < CURDATE()',
'order'=>'payment_date DESC'
),
))->findByPk($company_id);
You cannot put php date function into SQL statement in the way u did it. Try to use CURDATE()

Symfony mongo-odm-aggregation-bundle sums

For start, I have to say I am new to mongo (3.2). I am using mongo-odm-aggregation-bundle for php framework Symfony (2.8.4). I want to get sums of some fields restricted by dates.
So far, I managed to get sums for all records:
$expr = new \Solution\MongoAggregation\Pipeline\Operators\Expr;
$aq = $this->manager->getCollection('AppBundle:UserDaySums')->createAggregateQuery()->group([
'_id' => 'client.$id',
'total' => $expr->sum('$aSum'),
])
Now, I'd like to restrict this query by dateFrom,dateTo and userId. I am not sure, how to do it. I know, I should probably use match function, but I don't know how. Or is there some better solution?
Thanks for replies!
KP
Yes, you can use the match function. For example, the following assumes you have the date variables for use in the query:
$expr = new \Solution\MongoAggregation\Pipeline\Operators\Expr;
$aq = $this->manager->getCollection('AppBundle:UserDaySums')->createAggregateQuery();
$dateFrom = new MongoDate(strtotime('-2 days'));
$dateTo = new MongoDate();
$userId = 'Xsgy62js0lb';
$result = $aq->match(['dateFrom'=>$dateFrom, 'dateTo'=>$dateTo, 'userId'=>$userId ])
->group(['_id'=>'client.$id', 'total'=>$expr->sum('$aSum') ])
->getQuery()->aggregate();
In my case, match() was somewhat tricky on a MongoId object.
This didn't work for me:
$userMongoId = "57321c7a2977f8de306ef648";
$aq ->match([ 'user.$id' => $expr->eq($userMongoId) ])
This worked:
$aq ->match([ 'user' => new \MongoId($userMongoId) ])
Tested on Symfony 3 with the SolutionMongoAggregationBundle, MongoDB version 3.2.6.

How to get all users ever paid/complete an order?

I am working on a custom Magento Extension.
Here is how I take all customers in a customer group:
$customers = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToSelect('*');
foreach($customers as $customer)
{
$email=$customer->getEmail();
$CustomerPhone = $customer->getPrimaryBillingAddress()->getTelephone();
$CustomerName = $customer->getName();
$CustomerEmail = $customer->getEmail();
}
This how I get information about the users in a specific customer group.
How I can get all the users ever paid or complete (for example) an order?
This is 90% of the way there:
<?php
require_once '<path_to_magento_root>/app/Mage.php';
Mage::app('default');
$customers = Mage::getResourceModel('reports/customer_collection')
->setPage(0,10)
//->addAttributeToFilter('orders_count', array('gt' => 0))
->addOrdersStatistics();
foreach ($customers as $c) {
echo $c->getId().' - '.$c->getEmail().': '.$c->getOrdersCount()." orders, average amount ".$c->getOrdersAvgAmount().", sum amount ".$c->getOrdersSumAmount().PHP_EOL;
}
The missing 10% is that this lists all customers, and their order information, rather than only ones with at least one order (which will include in-progress orders - the addOrdersStatistics() includes any orders that aren't canceled).
I have that commented line in there, //->addAttributeToFilter('orders_count', array('gt' => 0)), because I thought that should do it, but it appears to be doing nothing at all. Still, I figured I'd put this much up at least, because maybe it's at least a step in the right direction.
Of course, you also could just loop through every order, and build an array of customers that fit your criteria, but that's probably going to be much, much slower than using Magento's reports models like this. As a last resort, though, it'd work. So would querying the database directly, for that matter.
Try following solution this should work for you.
$customers = Mage::getModel('customer/customer')
->getCollection()
->addAttributeToSelect('*');
$customers->joinTable(
array('sales/order'),
'customer_email=email',
array('*'),
null,
'right'
);
// print_r($customers->getData());
$data = $customers->getData();
foreach($data as $d)
{
//print_r($d); // print this to see the available fields
echo $d[customer_email]; //get the desired information
echo "<br>";
}

Yii DataProvider change the attributes of a column in each result

I'm using Yii's Dataprovider to output a bunch of users based on the column "points";
It works fine now but I have to add a feature so if the user is online, he gets an extra 300 points.
Say Jack has 100 points, Richmond has 300 points, However Jack is online, so Jack should rank higher than Richmond.
Here is my solution now:
$user=new Rank('search');
$user->unsetAttributes();
$user->category_id = $cid;
$dataProvider = $user->search();
$iterator = new CDataProviderIterator($dataProvider);
foreach($iterator as $data) {
//check if online ,update points
}
However, this CDataProviderIterator seems change my pagination directly to the last page and I can't even switch page anymore. What should I do?
Thank you very much!
Here is the listview:
$this->widget('zii.widgets.CListView', array(
'id'=>'userslist',
'dataProvider'=>$dataProvider,
'itemView'=>'_find',
'ajaxUpdate'=>false,
'template'=>'{items}<div class="clear"></div><div style="margin-right:10px;"><br /><br />{pager}</div>',
'pagerCssClass'=>'right',
'sortableAttributes'=>array(
// 'create_time'=>'Time',
),
));
Updated codes in Rank.php model
$criteria->with = array('user');
$criteria->select = '*, (IF(user.lastaction > CURRENT_TIMESTAMP() - 1800, points+300, points)) as real_points';
$criteria->order = 'real_points DESC';
However, it throws me error:
Active record "Rank" is trying to select an invalid column "(IF(user.lastaction > CURRENT_TIMESTAMP() - 1800". Note, the column must exist in the table or be an expression with alias.
CDataProviderIterator iterates every dataprovider value, and stops at the end. I don't know all about this classes, but think the reason is in some internal iterator, that stops at the end of dataprovider after your foreach.
Iterators are used when you need not load all data (for large amounts of data) but need to process each row.
To solve your problem, just process data in your view "_find". Add points there if online.
Or if you want place this logic only in the model (following MVC :) ), add method to your model:
public function getRealPoints() {
return ($this->online) ? ($this->points + 300) : $this->points;
}
And you can use $user->realPoints to get points according to user online status
update: To order your list by "realPoints" you need to get it in your SQL.
So use your code:
$user=new Rank('search');
$user->unsetAttributes();
$user->category_id = $cid;
$dataProvider = $user->search();
and modify $user->search() function, by adding:
$criteria->select = '*, (IF(online='1', points+300, points)) as real_points';
$criteria->order = 'real_points DESC';
where online and points - your table columns.

How to set current date and time in table field using zend

I am having table called users with following fields ,
is_login(tinyint(1)) and last_login(datetime).
Below is the piece of code to update when user is online using Zend,
public function updateLastLoginDetails($id){
$currentDateTime = date('Y-m-d H:i:s');
$data = array('is_online' => 1,'last_login'=>$currentDateTime);
$this->_db->update( 'users', $data,'id = '.$id);
}
Here i am using $currentDateTime = date('Y-m-d H:i:s'); to store current data and time. But it seems not ok with time.
Kindly suggest me the best way to store current data and time using Zend .
Thanks in Advance,
Dinesh Kumar Manoharan
I'm not exactly sure what's causing your problem, but I find using NOW() to be easier. Also, you should ensure the variable $id gets quoted in the update's where condition.
public function updateLastLoginDetails($id){
$data = array('is_online' => 1, 'last_login' => new Zend_Db_Expr('NOW()'));
$this->_db->update('users', $data, array('id = ?' => $id));
}
It looks like you forgot to use $data anywhere in your code!
public function updateLastLoginDetails($id){
$currentDateTime = date('Y-m-d H:i:s');
$data = array('is_online' => 1, 'last_login'=>$currentDateTime);
$this->_db->update('users', $data, 'id = '. (int)$id);
}
You might want to consider using a TIMESTAMP field in place of a DATETIME for last_login and have MySQL update it automagically.
Hi am I understanding correctly that the year month and day are being inserted correctly but not the hour minutes and seconds? If that is the case can you please provide use with a describe of the users table. Just execute "DESCRIBE users" in phpMyAdmin.
If that is the case it could be that the field is of type DATE and not DATETIME.

Categories