Get users who has bought this product (MAGENTO) - magento

Is it possible in magento to filter user based on the products they have bought?
For eg.
How can I get all the users who have bought product A from category B
mysql query like
SELECT users From table users, table products ..... WHERE user has purchased product A .
Please give some ideas, I needed to make this work.
Thanks

If you want an actual query, you can probably do something as simple as (add additional joins to get customer information from EAV):
SELECT DISTINCT o.customer_id FROM sales_flat_order_item i
INNER JOIN sales_flat_order o ON o.entity_id = i.order_id
WHERE o.customer_id IS NOT NULL
AND i.sku = 'some-product-sku'
Using Magento models, this should work for you:
<?php
require_once 'app/Mage.php';
/*
* Initialize Magento. Older versions may require Mage::app() instead.
*/
Mage::init();
/**
* Get all unique order IDs for items with a particular SKU.
*/
$orderItems = Mage::getResourceModel('sales/order_item_collection')
->addFieldToFilter('sku', 'some-product-sku')
->toArray(array('order_id'));
$orderIds = array_unique(array_map(
function($orderItem) {
return $orderItem['order_id'];
},
$orderItems['items']
));
/**
* Now get all unique customers from the orders of these items.
*/
$orderCollection = Mage::getResourceModel('sales/order_collection')
->addFieldToFilter('entity_id', array('in' => $orderIds))
->addFieldToFilter('customer_id', array('neq' => 'NULL'));
$orderCollection->getSelect()->group('customer_id');
/**
* Now get a customer collection for those customers.
*/
$customerCollection = Mage::getModel('customer/customer')->getCollection()
->addFieldToFilter('entity_id', array('in' => $orderCollection->getColumnValues('customer_id')));
/**
* Traverse the customers like any other collection.
*/
foreach ($customerCollection as $customer) {
var_dump($customer->getData());
}
It's pretty ugly though (instantiates multiple models, executes a bunch of queries under the covers), you could probably write your own model to make this -a lot- prettier.

You have to base your query on orders. If you want to do it by SQL query, you have to it by the following table:
sales_flat_quote, sales_flat_order_item to get the link between customer and product
catalog_category_product to get the link between category and product
catalog_product_entity to get the product id in function of the sku
...
Good luck

try these models
$orders = Mage::getModel('sales/order')->addAttributeToSelect('*')->getCollection();
$order_items = Mage::getResourceModel('sales/order_item_collection')
->addAttributeToSelect('sku')
->addAttributeToSelect('created_at')
->addAttributeToSelect('order_id')
->addAttributeToFilter('order_id', array('in' => $orders_ids))->load();

Related

Magento - assign multiple product ids to a category

I have a category "new" that I want to assign to, via a daily cron, the most recent 120 products.
I am trying to override the product ids assigned to a category.
Is there an easy way , like :
$category->setProductIds(array())
In PHP code you can put them into the category while you are importing them.
Say you have a product called $product and a category ID called $category_id
You can set the categories which a product belongs to by doing the following
$categories = array($category_id);
$product->setCategoryIds($categories);
$product->save();
f the product already has categories and you'd like to add one more then you can use getCategoryIds() like this:
$categories = $product->getCategoryIds();
$categories[] = $categoryId;
$product->setCategoryIds($categories);
$product->save();
it works like this
$category = Mage::getModel('catalog/category')->load($categoryID);
$product_array = $category->getProductsPosition()
... make changes ... format : $item[$product_id] => $position_in_category
$category->setPostedProducts($product_array);
$category->save();
To Remove product from category:
Mage::getSingleton('catalog/category_api')->removeProduct($category->getId(),$p‌​roduct->getId());
To Add Product to Category:
Mage::getSingleton('catalog/category_api')->assignProduct($category->getId(),$p‌​roduct->getId());
Now you can loop through all products and assign those to category using category id.
Note: This will not overwrite any categories the product is already in.

getStoreCategories() to get categories by ids

I would like to get an array of categories for my magento store.
I need to use following unit for my website to work:
$categories = $helper->getStoreCategories('name', true, true);
However this lists all categories.
I would like to select categories that are important for me. I think I could do that by selecting ids of the categories or names of the categories but I don't know how to do it.
Could anybody help me please?
Let's say you have an array with category ids like this:
$ids = array(6,8,99);
You can get the category objects like this:
$collection = Mage::getModel('catalog/category')->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('entity_id', $ids);
if you want only active categories add this line also
$collection->addAttributeToFilter('is_active', 1);
Use this function and just pass category Id:
function getCategoryData($_categoryId=null) {
// For category Collection
$category = Mage::getModel('catalog/category')->load($_categoryId);
// For product Collection category wise
$prodCollection = $category->getProductCollection();
return $prodCollection;
}

Magento Credit Memos Model

Can anyone help with the model/collection to search through all credit memos within magento as opposed to orders?
I can use Mage::getModel('sales/order') for orders but not seeing for credit memos
Kind regards
I put this together quickly. For example, let's say you wanted to grab the comments, you can do something like this.
Get CreditMemo Comment Based on Order
$incrementId = 100000002;
$collection = Mage::getResourceModel('sales/order_creditmemo_collection')
->addAttributeToFilter('increment_id', $incrementId);
foreach($collection as $item) {
$creditMessage = Mage::getResourceModel('sales/order_creditmemo_comment_collection')
->addAttributeToFilter('entity_id', $item->getEntityId());
foreach($creditMessage as $message) {
echo $message->getComment();
}
}
You can filter the collection with the increment_id or even the order_id :)
Get All Comments
$collection = Mage::getResourceModel('sales/order_creditmemo_comment_collection');
Below is a list of tables for creditmemo
sales_flat_creditmemo
sales_flat_creditmemo_comment
sales_flat_creditmemo_grid
sales_flat_creditmemo_item
Hope this helps!
right way to get Credit Memo comment collection
$collection = Mage::getResourceModel('sales/order_creditmemo_collection')
->addFieldToFilter('order_id', $order->getId()); /* here we have no load memo by order id not increment id.Increment id is the creditmemo increment id not order increment id. */
foreach($collection as $item) {
$creditMessage = Mage::getResourceModel('sales/order_creditmemo_comment_collection')
->addAttributeToFilter('parent_id', $item->getId()); /* here we need to use parent_id not entity_id.*/
}
var_dump($creditMessage->getData());
exit();

How to exclude a category from a magento getCollection

this might be a silly question, but well. I have the following code that retrieves all the products on my shop.
$products = Mage::getModel('catalog/product')->getCollection();
$products->addAttributeToFilter('status', 1);
$products->addAttributeToFilter('visibility', 4);
$products->addAttributeToFilter('type_id', 'simple');
$products->addAttributeToSelect('*');
$products->addStoreFilter($storeId);
$prodIds = $products->getAllIds();
Im aware of the:
$category = Mage::getModel('catalog/category')->load(9);
$products->addCategoryFilter($category);
to filter by a category ID, but how to get all products except one specific category ID ? (Magento 1.6.2)
I think this should work, presuming you know what category ID you want to filter out, but I can't test it right now
$catId = 9;
/* I'm almost positive 'e' is the alias used for catalog_product_entity, check your
query with echo (string) $products->getSelect(); if it doesn't work */
$products->getSelect()->join(array('cats' => 'catalog_category_product'), 'cats.product_id = e.entity_id');
$products->getSelect()->where('cats.category_id', array('neq' => $catId));
This is what I used:
$_productCollection = Mage::getModel('catalog/product')
->getCollection()
->addAttributeToSelect('*')
->addUrlRewrite();
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($_productCollection);
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($_productCollection);
$_productCollection->load();
$_productCollection->getSelect()->join(array('cats' => 'catalog_category_product'), 'cats.product_id = e.entity_id');
$_productCollection->getSelect()->where('cats.category_id not in (41)');
Here is the logic I came up with to resolve this problem.
Note: Should work in Magento 1.X
It dynamically pulls table names so that it would work in any installation.
It validates that it is a correct catalog/category entity ID.
It uses a unique table alias by category ID when performing the MySQL LEFT JOIN. This allows us to exclude the collection from multiple category IDs.
It validates that we do not attempt to exclude the collection from the same category id twice.
public function addCategoryExclusionFilter(Mage_Catalog_Model_Resource_Product_Collection $collection, $category_id)
{
/* #var $resource Mage_Core_Model_Resource */
/* #var $category Mage_Catalog_Model_Category */
$resource = Mage::getModel('core/resource');
$category = Mage::getModel('catalog/category')->load($category_id);
$select = $collection->getSelect();
$tblccp = $resource->getTableName('catalog_category_product');
$tblAlias = $tblccp.'_'.$category_id;
if (! $category->getId()) {
Mage::throwException("Invalid `{$resource->getTableName('catalog/category')}`.`entity_id` value ({$category_id}).");
}
if (strpos($select->__toString(), $tblAlias) !== false) {
Mage::throwException("Category (ID: {$category->getId()}) already excluded from collection");
}
$select->joinLeft(array($tblAlias => $tblccp), "(`{$tblAlias}`.`product_id` = `e`.`entity_id` AND `{$tblAlias}`.`category_id` = '{$category->getId()}')", array());
$select->where("`{$tblAlias}`.`category_id` IS NULL");
}
Example of the MySQL query afterwards:
SELECT
`e`.*
FROM
`catalog_product_entity` AS `e`
LEFT JOIN
`catalog_category_product` AS `catalog_category_product_28` ON (
`catalog_category_product_28`.`product_id` = `e`.`entity_id` AND
`catalog_category_product_28`.`category_id` = '28'
)
WHERE
(`catalog_category_product_28`.`category_id` IS NULL)
What we are doing here is performing a join on the table which holds the relationship between product entities and category entities, BUT only where the record's category_id is equal to the category id which we are looking to exclude. This is important because the catalog_product_entity table has a 1:M relationship to the catalog_category_product table (at the time of posting this answer, I do not see the other answers here addressing this). Then, we add a WHERE declaration that we only want to select records where the category_id column for the joined table IS NULL (because there exists no record in the joined table, for product entities which we wish to select).

Update all Tier prices for a product

Without directly querying the Magento database. How can i remove all the tier prices for a certain product based on quantity and customer group?
Then add new tier prices for this product.
Example:
Remove all tier prices for a product with the SKU: FD001
where the customer group id is: 4
PHP 5.3
Magento 1.4.2
You first have to unset the tier prices and save the product, then add the tier price(s) and save again.
Mage::getModel("catalog/product")->load(123)
->unsTierPrice()
->save()
->setTierPrice(array(
array(
'website_id' => 0,
'all_groups' => 0,
'cust_group' => 4,
'price' => 99.99,
'price_qty' => 1
),
array() // another tier, etc
))
->save();
I ended up solving this by using direct database queries.
As always I'm looking for a better answer.
My Hacky solution:
$product = Mage::getModel('catalog/product')->load(9999);
$dbc = Mage::getSingleton('core/resource')->getConnection('core_write');
$dbc->query('DELETE FROM `catalog_product_entity_tier_price` WHERE `entity_id` = ' . intval($product->getId()) . ' AND `customer_group_id` IN(3,4,6,7) AND qty = 1');
$dbc->query(
'INSERT INTO `catalog_product_entity_tier_price` (`entity_id`,`all_groups`,`customer_group_id`,`qty`,`value`,`website_id`)
VALUES ('. intval($product->getId()) . ',0,' . intval($id) . ',1,' . floatval($price) . ',0)'
);
There's an API available for the product tier price.
Alternatively, you can use some PHP code that uses the Magento code to query for a list of products that match those criteria and then adjust each one. Alan Storm has an article about how Model Collections work (they're the type of object that you would use for this).
Basically it would be something like this to delete the products, I'm not sure how you would set the tier prices, but you can a look at the generated phpdoc documentation. I'm selecting every product that matches customer_group 4 and then deletes each product. You'll have to figure out how to filter things out based on the tier price...
<?php
require 'app/Mage.php';
$app = Mage::app('default'); // Mage_Core_Model_App
$store = $app->getStore(); // Mage_Core_Model_Store
$products = Mage::getModel('catalog/product')->getCollection();
// filter out anything that doesnt match the customer group 4
$products->addFieldToFilter('customer_group', '4');
// loop through each product and delete it
for ($products->load() as $product) {
$product->delete();
}
#omouse's answer pointed us to Magento's API for tier prices. [Updated Link for Magento 1.X's Tier Price API] Note: I'm working with Magento 1.9.2.2.
After looking around for the most efficient way to update a product's tier prices (without using direct SQL), I found the API is the fastest way. It's still slow, but it's better than the other methods I found which recommended doing something like:
// Works, but is slow
$product = Mage::getModel('catalog/product')->load($productId);
$product->unsTierPrice();
$product->save();
$product->load();
$product->setTierPrice($tiers);
$product->save();
Better, I made my array of tier arrays into an array of tier objects, and used the API functions to update the product:
// Build the array of tier level objects
foreach ($tierLevels as $tierLevel) {
$tiers[] = (object) array(
'website' => 'all',
'customer_group_id' => 'all',
'qty' => $tierLevel['min_qty'],
'price' => $tierLevel['unit_price']
);
}
// Use the API to do the update
try {
$tierPriceApi = Mage::getSingleton('catalog/product_attribute_tierprice_api_v2');
$tierPriceApi->update($productId, $tiers);
}
catch (Exception $e) {
// Handle the exception
}
I searched a while to find a solution, which is not pure SQL and does not need a product save, because we want to update tier prices for a catalog of 50k products, so saving all of them is surely not a solution.
I think I finally found a good way.
Mage::getResourceSingleton('catalog/product_attribute_backend_tierprice')
->deletePriceData($product->getId());
$newTierPrice['entity_id'] = $product->getId()
$newTierPrice['all_groups'] = 1;
$newTierPrice['customer_group_id'] = 0;
$newTierPrice['qty'] = 42;
$newTierPrice['value'] = 100;
$newTierPrice['website_id'] = 0;
Mage::getResourceSingleton('catalog/product_attribute_backend_tierprice')
->savePriceData(new Varien_Object($newTierPrice));

Resources