If I programmaticly add a item to a shopping cart (setting its custom options) then add another instance of the same item to the cart (with its custom options set to different values), "view cart" lists each item instance on a separate line (good). However, if when adding the items, I programmaticly set one item's special price (via SetSpecialPrice), both item prices change to that special price.
How do I limit the effects of SetSpecialPrice to only the item instance I call that method on?
Thank you,
Ben
To the code you are adding the same 'item' to the quote. This could probably be considered a bug.
You may have to go lower level. What method are you using to add the items to the cart? You may need to emulate what that method does yourself (violating DRY principles) to force it to create a new 'item.'
... going to look in the code now.
Ok, looking at Mage/Sales/Model/Quote.php line 935: public function getItemsByProduct - this is where it determines if the product you are adding already exists. It calls $item->representProduct, which is in Mage/Sales/Model/Quote/Item.php line 301: public function representProduct
If you override this class in your module/code and replace this method you should be able to add simple code that detects if there is a difference in special price and react accordingly.
Code snipet:
$specialPrice = $product->getSpecialPrice();
$thisSpecialPrice = $itemProduct->getSpecialPrice();
if((is_null($specialPrice) xor is_null($thisSpecialPrice))||
(!is_null($specialPrice) && !is_null($thisSpecialPrice && $specialPrice!=$thisSpecialPrice))){
return false;
}
Related
What I'm trying to do:
Im developing a POS module for Odoo.
When creating a new payment method for odoo pos, theres a 'use payment terminal' section that has a list of all available payment terminals. This list is a computed field in the DB called 'use_payment_terminal'. I want to add my custom module to that selection.
What i've already done:
The computed field is populated by a '_get_payment_terminal_selection' function that I overrodde:
def _get_payment_terminal_selection(self):
return super(PosPaymentMethod, self)
._get_payment_terminal_selection() + [('xxx', 'xxx')]
I added a post init hook that tried to calls the above function directly, cause I wasn't sure want the problem was and assumed that the function wasn't being called when expected.
The problem:
Neither of these solutions has worked and the selection still doesn't display what I expect it to. Any suggestions on why that might be ?
Try this way :
def _get_payment_terminal_selection(self):
return super(PosPaymentMethod, self)._get_payment_terminal_selection() + [('xxx', 'xxx')]
I want to make 3 dependents drop down list, each drop down dependent to the previous drop down, so when I select an item from first drop down , all data fetch from database and add to second drop down as item.
I know how to do this in a normal php page using ajax, but as opencart uses MVC I don't know how can I get the selected value
Basically, you need two things:
(1) Handling list changes
Add an event handler to each list that gets its selected value when it changes (the part that you already know), detailed tutorial here in case someone needed it
Just a suggestion (for code optimization), instead of associating a separate JS function to each list and repeating the code, you can write the function once, pass it the ID of the changing list along with the ID of the depending list and use it anywhere.
Your HTML should look like
<select id="list1" onchange="populateList('list1', 'list2')">
...
</select>
<select id="list2" onchange="populateList('list2', 'list3')">
...
</select>
<select id="list3">
...
</select>
and your JS
function populateList(listID, depListID)
{
// get the value of the changed list thorugh fetching the elment with ID "listID"
var listValue = ...
// get the values to be set in the depending list through AJAX
var depListValues = ...
// populate the depending list (element with ID "depListID")
}
(2) Populating the depending list
Send the value through AJAX to the appropriate PHP function and get the values back to update the depending list (the part you are asking for), AJAX detailed tutorial here
open cart uses the front controller design patter for routing, the URL always looks like: bla bla bla.bla/index.php?route=x/y/z&other parameters, x = folder name that contains a set of class files, y = file name that contains a specific class, z = the function to be called in that class (if omitted, index() will be called)
So the answer for your question is:
(Step 1) Use the following URL in your AJAX request:
index.php?route=common/home/populateList
(Step 2) Open the file <OC_ROOT>/catalog/controller/common/home.php , you will find class ControllerCommonHome, add a new function with the name populateList and add your logic there
(Step 3) To use the database object, I answered that previously here
Note: if you are at the admin side, there is a security token that MUST be present in all links along with the route, use that URL:
index.php?route=common/home/populateList&token=<?php echo $this->session->data['token'] ?> and manipulate the file at the admin folder not the catalog
P.S: Whenever the user changes the selected value in list # i, you should update options in list # i + 1 and reset all the following lists list # i + 2, list # i + 3 ..., so in your case you should always reset the third list when the first list value is changed
P.P.S: A very good guide for OC 1.5.x => here (It can also be used as a reference for OC 2.x with some modifications)
I haven't been able to find where does the output of getPaymentHtml() comes from.
Its defined as:
public function getPaymentHtml() {
return $this->getChildHtml('payment_info');
}
I couldn't find out the template for payment_info block.
Basically I want to be able to retrieve credit card type and credit card number in the progress block of checkout.
How do I find out the method names? Something like $this->getCreditCardType()
Edit: OK! I understand that Magento figures out the payment method first which has their corresponding templates which are used to render output. But in progress.phtml of checkout, var_dump( $this instanceof Mage_Payment_Block_Info_Cc ); returns false, so how do I access that in current context?
The Progress block doen't have it's own template for Payment info. Mage_Checkout_Block_Onepage_Payment_Info block uses the selected Payment Method block to output html. Look at the Mage_Checkout_Block_Onepage_Payment_Info::_toHtml() method:
protected function _toHtml()
{
$html = '';
if ($block = $this->getChild($this->_getInfoBlockName())) {
$html = $block->toHtml();
}
return $html;
}
To find the actual template and block for the specific Payment method you use, you need to perform next steps:
First - get model alias for current payment method Mage::getStoreConfig('payment/'.$yourMethod.'/model') and instantiate it using Mage::getModel(alias)
then get block type using $model->getInfoBlockType() - so you'll be able to find the actual Block by it's type
For example for ccSave payment method the info block is Mage_Payment_Block_Info_Ccsave, and template for it is app\design\frontend\base\default\template\payment\info\default.phtml. You'll be able to find all data inside those.
Good luck ;)
For the sake of completeness, exact functions to fetch CC type and last 4 digits of CC number are:
echo Mage::getSingleton('checkout/session')->getQuote()->getPayment()->getCcType();
echo Mage::getSingleton('checkout/session')->getQuote()->getPayment()->getCcLast4();
The block class is declared in layout update XML; see the onepage checkout and multishipping directives from checkout.xml. The actual child block which is used depends on the payment model which is being used, but there is a common template that will be used unless overridden.
Example:
See the generic CC method model Mage_Payment_ModelMethod_Cc
From that see its info block Mage_Payent_Block_Info_Cc...
...which will lead you to the "base" payment info block Mage_Payment_Block_Info which sets a default template.
Edited to include SSCE
I have a Proc object which I add to a Hash with other Procs:
ten_percent_discount_over_sixty = Proc.new {
cart.each { |item| cart_total += item.price }
if cart_total >= 60.00
cart_total =- cart_total * 0.1
end
}
As you can see there is a cart array which contains items. I can't however get my cart instance variable into the scope of this proc. So later when I iterate through all of these rules in another method, I get undefined variable errors.
The point of doing this is that I have various promotional rules (functions) that need to be run on this cart object. It's possible there's a better way to store rules that can be applied iteratively to a objects instance variable.
I have checkout object which contains a cart (an array) of item objects; items have the attributes: code, price and name.
Next I have a Promotion object which holds a hash of promotional rules. This hash contains Proc objects that hold these rules (which are functions that each run on the cart object changing the final price of the cart). Rules maybe added and removed by calling a method and with the name as an argument.
The problem I am having is when I iterate through the hash of promotional rules. I don't know how to get the cart object into the scope of those Proc objects in order to run the functions contained in those Proc objects, changing the cart state.
Do I pass in the cart object when creating the Proc/lambda?
Create a cart instance variable in the Promotion object and set/get it?
Somehow pass in the cart variable within the checkout object?
I'm over-thinking or approaching the problem in an incorrect manner?
The full code is quite long so I'll post a gist below:
https://gist.github.com/3163127
Your rule procs must accept cart as an argument, act on it, and return modified cart.
cart = {total: 100}
rules = {ten_percent_discount: lambda{|c| c[:total] *= 0.9; c },
five_percent_discount: lambda{|c| c[:total] *= 0.95; c}}
rules.each do |name, rule|
cart = rule.call cart.dup
end
cart # => {:total=>85.5}
How can i select Ajax Dropdown suggestion list item using selenium code for firefox??
My problem is :the Ajax dropdown list is visible but it is not selected and next steps gets stuck.
May be selenium is waiting for something.
the list that page populates is dynamic and in bla bla tags.
Please help with a example code.
How can i use waitfor* here.
Remember i am not using firefox ide but i am writing a code.
Please help.
I had a similar problem whereby, selenium was able to find the dropdown menu but was unable to click on the visible text. I later found out that there was an Ajax call that was populating the dropdown menu data and as a result selenium seemed to not be able to select the intended visible text because the list items had not been fully populated. That is, by the time the script was selecting my option value, Ajax had not completely loaded the menu options. Here's my solution:
public void nameOfCollegeList(String optionItem) {
// declare the dropdownMenu web element
WebElement dropDownMenu = driver.findElement(By.cssSelector("#CollegeNames"));
// click on the dropdownMenu element to initiate Ajax call
dropDownMenu.click();
// keep checking the drop down menu item list until you find the desired text that indicates that the menu has
// been fully loaded. In this example I always expect "Other (please specify)" to be the last item in the drop down menu.
// If I don't find the expected last item in the list in my if condition, execute the else condition by calling the
// same method(recursively). Please note that if the "if" statement is never satisfied then you'll end up with an
// infinite loop.
if (dropDownMenu.getText().contains("Other (please specify)")) {
new Select(dropDownMenu).selectByVisibleText(optionItem);
}
else {
nameOfCollegeList(optionItem);
}
}
i am little confused with your question at " :the Ajax dropdown list is visible but it is not selected "
this sounds like that the element is disabled. (Java coding)
if so selenium.isElementDisabled()
if not then,
1) programming laguage solution using while loop and isElementPresent() OR isElementDisabled()
//trigger the Ajax request and then
long initialTime = System.currentTimeMillis();
do{
thread.sleep(1000);
}while((!selenium.isElementPresent("AjaxElement")) && (System.getCurrentTimeMillis() - initialTime <= 5000)) ;
//some thing like above for client programming solution...but for,
2) selenium's inbuilt solution
we have a method called waitForCondition("java script to be executed", "time out value");
this method loops the javascript statement until it returns true or the supplied time out occurs
here the important thing is analyzing the application/Ajax element to find out which particular condition of the element changes.
from your explation my guess is this, display=none will be changed to display=block OR
disabled=true will be changed to disabled=false OR isReadOnly will be changed to no such attribute ect.....(you need to figure out this)
and then, use this attribute = value to build a javascript function as ,
selenium.waitForCondition("window.document.getElementById('AJAX ELEMENT').disabled == 'false'", "3000");
you can work out the above statement however you want in your programming language.
try {
//do the action which triggers the Ajax call
selenium.waitForCondition("window.document.getElementById('AJAX ELEMENT[drop down element]').disabled == 'false'", "3000");
//OR
selenium.waitForCondition("window.document.getElementById('AJAX ELEMENT').disabled == 'false'", "3000");
}
catch(SeleniumException se)
{
if((se.getMessage()).toLowerCase().contains("timed out")
throw //..some a custom exception however your organisation requires
}
selenium.select("drop down element id", "option id");
and so on.....