I have a bit of an odd situation that I am trying to fix. Magento v1.9.2.4
I have only 2 different attribute sets. A and B.
I want to display the stock quantity/availability for set B, but not
set A.
To make things a bit more complex, I have 14 Customer Groups, I only want 6 of those groups to ever see any quantities/availability.
Here's what I have done so far to arrange this:
$customerSession = Mage::getSingleton('customer/session');
if($customerSession->isLoggedIn()){
$groupId = $customerSession->getCustomerGroupId();
$group = Mage::getModel('customer/group')->load($groupId);
if ('custgroup_1' == $group->getCode()){
$qty = (int) Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product)->getQty();
echo 'Quantity Available: ' . $qty;
}
}
The above snippet is repeated 5 times with the [if ('custgroup_1' ...] changed to accommodate the group I need this to show up for. That part is working just fine.
I only need to specify somehow that I only want the availability to show up for the attribute set B. Then Regardless of the customer group never show the qty/availability for attribute set A.
I have tried playing with the inventory options on the product page. (disabled stock management = qty still shows | enabled stock management, set qty to 0 and my custom options disappear | ect.) Nothing within the magento backend seems to work.
I'm a newbie to this whole Magento/Dev thing. So I apologize if this is considered a silly question.
Thank you for any/all help!
So, Immediately after posting this I realized I was thinking about the problem all wrong.
Because any item that isn't in attribute set B isn't having stock managed, I was able to write a condition that enables output only for products that have an inventory level greater than 0.
Here is the code for anyone who might happen to need to show a quantity for products based on a customer group, and hide availability for any item that has inventory management set to no, but is set to "In Stock".
$customerSession = Mage::getSingleton('customer/session');
if($customerSession->isLoggedIn()){
$groupId = $customerSession->getCustomerGroupId();
$group = Mage::getModel('customer/group')->load($groupId);
if ('custgroup_1' == $group->getCode()){
$__manStock = $_product->getStockItem()->getManageStock();
$__invAmt = (int)Mage::getModel('cataloginventory/stock_item')->loadByProduct($_product)->getQty();
if ($__manStock > 0)
echo $this->__("Available Qty: $__invAmt");
}
}
Related
I want to simply change the shipping method of an order on Woocommerce.
I have seen a few posts on editing shipping methods on orders but I'm not 100% clear on the exact protocol of how it works, I have a rough idea but no success yet! If you can help me to get the order to update its shipping method that would be awesome! (this is the middle of a large project so I can't share the whole plugin, let me know if you need anymore details happy to provide anything that's necessary!)
I have this small bit of code that returns me a list of orders that need shipping method updated and the new shipping method rateID that it has to be changed to, that all works fine but i have included it so you can see where it comes from.
Once the array of orders to be updated has been constructed, it then needs to be processed using the set_shipping() method. One at a time working through the array items and updating the shipping method of each, from the original to the new one provided in the toUpdate array
UPDATED: i have tried using the WC_API_Orders() class as set_shipping is a method of that. still coming up with the unrecognised error.
'Class 'Inc\Api\Callbacks\WC_API_Orders' not found'
private function updateRound()
{
if (! empty($_POST['update'])) {
$updateorderID= $_POST['orderID']; //get list of orderID to change
$updateRound= $_POST['newRound']; //list of rounds new orders want swapped to
$updateList= $_POST['update']; //uses a check box to confirm user wants to update row (stops accidentally updating the whole list)
// print_r($_POST['update']); //shows an output to check results.
$toUpdate = []; //this is the array for all the shippingmmethods to update on set order etc.
//make list of order ID's to update and their new shipping method
foreach ($updateList as $key => $value) {
$toUpdate[] = [
'orderID' => $key,
'newRound' => $updateRound[$key]
];
}
}
$absOrder = new WC_API_Orders();
foreach ($toUpdate as $updateOrder) {
//echo "</br>OrderID: ".$updateOrder['orderID']." Round updated to ".$updateOrder['newRound'];
echo "order ".$updateOrder['orderID']."updating";
$absOrder->wc_get_order($updateOrder['orderID']);
echo " order retreived";
$absOrder->set_shipping($order, $updateOrder['newRound'], 'update' );
echo "updated </br>";
}
}
This is for a very local veg delivery scheme, people can only place an order if their postcode is in the set group, so that's not so important, this shipping method we use to change from 'wed round' to 'thurs round' etc. Simple really no concern for delivery companies etc, its all in house. Tax etc. doesn't matter, it's all done elsewhere, this is simply meant to be a way of editing orders onto delivery rounds.
Regarding OpenCart store selling digital downloads.
I am trying to add a script to the product page to warn the customer if that specific product (download) is already purchased and exists in Account>Downloads.
The reason is to avoid customers purchasing the same product twice.
Appreciate your help.
Edit:
I have tried getting the product IDs of all orders by a customer using a SQL query and that works fine externally but inside OpenCart I am facing issues.
A query such as:
SELECT product_id
FROM ocuk_order_product
WHERE order_id IN (
SELECT order_id
FROM ocuk_order
WHERE customer_id = 'xxxx'
)
My main problem is not being sure how to get similar results in OpenCart Product page. (Which pages and path exactly and where inside the files)
Tried this post as well: Opencart get product downloads
But it is not exactly working on product page (product.php)
Opencart Version 3.0.2.0
Ok I'll take a stab at this but let's clarify a few things:
1) DB_PREFIX is simply a php constant that's declared in your config.php file. Based on the query you provided it's probably equal to ocuk. The point is, you write queries using this constant and they become portable across installations regardless of the users' chosen database prefix.
2) Opencart is based on the MCVL (an extension of MVC which includes language files) structure. The place to execute queries is in the model. The place to call model methods is in the controller. The controller passes output to the view and often uses language variables from language files.
So what I would do is write function and put it in your product model – in this case that's catalog/model/catalog/product.php. This function is called a method since it's now part of your model class. The function will output the rows in your table that a logged in customer has purchased the given product. It's also important to check (a) that the customer is logged in and (b) that the orders you are querying against are real orders - with an order_status_id > 0. We can go into that but suffice to say that you always need to check the order_status_id if you want to know about actual completed orders. Such a method could look something like this:
public function getOrderProductHistory($product_id) {
$result = [];
if ($customer_id = $this->customer->getId()) {
$sql = "
SELECT *
FROM " . DB_PREFIX . "order o
JOIN " . DB_PREFIX . "order_product op USING (order_id)
WHERE o.order_status_id > 0
AND o.customer_id = '" . (int)$customer_id . "'
";
$query = $this->db->query($sql);
$result = $query->rows;
}
return $result;
}
Now in your controller (on a product page that's catalog/controller/product/product.php) you can call this method to get results like this:
$order_product_history = $this->model_catalog_product->getOrderProductHistory($product_id);
And then do something based on the output:
if ($order_product_history) {
$data['has_been_ordered'] = true;
} else {
$data['has_been_ordered'] = false;
}
Now $has_been_ordered is a boolean that you can access in your view to display a message to the customer. There's still a bit more code for you to write but hopefully this helps get you off to a good start.
I apologize ahead of time for the crappy question title I couldnt figure out a good way to summarize the solution Im looking for in a sentence.
Platform is Magento/PHP but the Magento part isnt really a part of this problem. Basically we have a service at checkout (just a dropdown box) for customers to select a future date for their order to ship. Ive been tasked with limiting the display of this service to only a few products.
If an order contains one or more of a permitted product, or, several of the products that are permitted it would display the dropdown box.
If the order contains a mix of permitted and non-permitted products obviously it would not show the dropdown box.
I created a new product attribute called "can_futureship" and set the value to True for the few products that are permitted to ship on a future date. My problem now is I cant seem to grasp the best way to single out those products.
There is a chunk of code (foreach loop) that goes through all the items in the cart and checks them for other restrictions and attributes so I know I need to put it in that loop. Especially in the cases of mixed True and False conditions. For example some pseudocode:
Product1 = True
Product2 = True
Product3 = True
$can_futureship_show_drop_down = false;
foreach(Items as item) {
$product['can_futureship'] = model->getattribute('can_futureship');
if ($product['can_futureship'] = TRUE) {
$can_futureship_show_drop_down = true;
}
}
That was my initial line of thinking and would obviously work if all the products are true or the last product in the array is true but I need it to end up false if there any false results at all. I was also thinking that maybe I should load all results into an array and check for false results that way? Any help is greatly appreciated!
Think the other way ;)
$can_ship_future = true;
foreach($products as $product) {
if ( ! $product->canShipFuture() ) {
$can_ship_future = false;
break; // Don't need to check the other products
}
}
I am finding some odd behavior when I try to save a product model from a script it Magento Enterprise 1.8 that has tier pricing.
Take this code for example:
// This product has a tier price
$product = Mage::getModel('catalog/product')->load(194760);
$product->setName('Changed Product Title');
$product->save();
When saving a get an exception (detailed below). However if I change nothing in the model, I do not get the exception. I have a feeling that this is due to the fact that I did not update anything so Magento does not do as much work.
// Same product, but I changed nothing and it works
$product = Mage::getModel('catalog/product')->load(194760);
$product->save();
The odd part is that I am able to save the product successfully if I am setting or modifying tier price information (pending I do not create anything that is duplicated)
// This works pending the tier price does not already exist
$mud_array = array();
$mud_array[] = array(
'website_id' => 0,
'cust_group' => 32000,
'price_qty' => 5,
'price' => 6
);
$product = Mage::getModel('catalog/product')->load(194760);
$product->setTierPrice($mud_array);
$product->save();
The exception that I am seeing is as follows:
Fatal error: Uncaught exception 'Mage_Eav_Model_Entity_Attribute_Exception' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '194760-1-0-5.0000-0' for key 'UNQ_CATALOG_PRODUCT_TIER_PRICE'' in /path/to/magento/app/code/core/Mage/Eav/Model/Entity/Abstract.php:61
So it appears that when a tier price exists in a product, and you try to change anything inside the model, it will attempt to reinsert all the tier price information.
Has anyone seen this before? Is there a way to work around this? Thanks for any help you can provide.
I had the same problem with EE 1.12, but with the "group_price" attribute. Just managed to fix the error by adding at the begging of my script
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
Ok so I created a fix for this that seems to work.
In /app/code/core/Mage/Catalog/Model/Resource/Eav/Mysql4/Product/Attribute/Backend/Tierprice.php there is a function called savePriceData. From what I can gather this function is responsible for determining if we need to update or insert a tier price.
There is an if block that makes this decision to update or insert based on the information coming from the $priceObject that is passed to the function.
If you are updating a tier price from the admin panel, priceObject has two values value_id and value. These fields both point to columns in the catalog_product_entity_tier_price table. This is what happens in the first part of the if block
If you are creating a new tier price from the admin panel, priceObject has all the columns from the catalog_product_entity_tier_price table (entity_id, all_groups, customer_group_id, qty, value, and website_id). Magento then takes this information and inserts it into the catalog_product_entity_tier_price table.
The actual problem was that when you save a product from a script (aka outside the admin panel) you ALWAYS get a priceObject that contains all the information for an insert. So it will always try to do the insert into the table which if it already exists causes an integrity constraint violation.
So the fix I put together for this was really quite simple. In the second part of the if block, I am doing a check to see if the tier price already is in the table and if it is, I simply do not do the insert. Here is the code:
... first part of if statement
// somehow we need to have this not happen if it already exists
$reader = $this->_getReadAdapter();
$sql = "SELECT * FROM catalog_product_entity_tier_price WHERE ";
foreach($data as $index => $value) {
$sql .= $index . ' = ' . $value . ' AND ';
}
$sql = substr($sql, 0, -4);
$search = $reader->fetchAll($sql);
if(count($search) > 0) {
// It already exists, don't do anything
} else {
$adapter->insert($this->getMainTable(), $data);
}
Obviously, you really should make sure that you copy this file to local before you make this change (or probably better yet, rewrite it in a module). This probably is not the most 100% correct "Magento way" to do this, but I really needed to get a solution for this ASAP.
I am open to better solutions than this, but I wanted to share what I found
(Note: As I am on the Enterprise Edition of Magento, I did not want to share anymore of the source than necessary since it could be a violation of our license agreement)
I have an issue. I want to show 4 related products in the product page. That is simple and I have done that. But if the product doesn't have any or has less than 4 products I want the remaining product to randomly appear in the page.
To select 4 random products first you need rewrite class that responsible for related block (or just move this file to local folder) and change logic for function that returns collection to something like next code:
$productsCollection = Mage::getResourceModel('catalog/product_collection');
$productsCollection->getSelect()->order('rand()');
$productsCollection->getSelect()->limit(4);
Hope, it will be helpful
If you're only interested in creating this functionality on the product page you can find most of the magic in Mage_Catalog_Block_Product_List_Related::_prepareData().
To fill out your related products with random products, we first need to know exactly how many random products we'll need. In this case, it's (4 - related products found):
// Existing Magento code near end of method
$this->_itemCollection->load();
// Our code
$numRandomsToGet = 4 - count($this->_itemCollection);
Then we can fetch the appropriate number of random products and add them to the collection:
// Our code
$randCollection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($randCollection);
$randCollection->getSelect()->order('rand()');
$randCollection->addStoreFilter();
$randCollection->setPage(1, $numRandomsToGet);
$randCollection->addIdFilter($this->_itemCollection->getAllIds(), true);
foreach($randCollection as $randProduct)
{
$this->_itemCollection->addItem($randProduct);
}
// Existing Magento code
foreach ($this->_itemCollection as $product) {
$product->setDoNotUseCategoryId(true);
}
return $this;
Caveat/Plug: I pulled this code from our Related Products Manager extension for Magento so there might be some fiddling external to this method that needs to get done but I don't think so. If you get stuck you can try downloading the extension and examining the code in its entirety. Or, of course, you can just use the extension as-is.