Event to track quote changes in magento - magento-1.9

I want an observer to track changes in Quote like when removing products, updating, adding product from frontend and backend as well. This observer should run after magento native code.
There are many events like below which are executed during quote but I am not sure which observer will be fit for my requirement--
sales_quote_remove_item
sales_quote_add_item
sales_quote_product_add_after
sales_quote_item_collection_products_after_load
checkout_cart_add_product_complete
checkout_cart_save_before
checkout_cart_save_after
etc...

You may not be able to achieve this by using a single event , but instead you could write a single observer and call this observer for multiple events..
<sales_quote_product_add_after>
<observers>
<sales_quote_product_add>
<type>singleton</type>
<class>my_module/observer</class>
<method>myfunction</method>
</sales_quote_product_add>
</observers>
</sales_quote_product_add_after>
<checkout_cart_add_product_complete>
<observers>
<checkout_cart_add_product>
<type>singleton</type>
<class>my_module/observer</class>
<method>myfunction</method>
</checkout_cart_add_product>
</observers>
</checkout_cart_add_product_complete>
Events you can see
sales_quote_remove_item
sales_quote_item_qty_set_after
sales_quote_product_add_after
https://www.nicksays.co.uk/magento-events-cheat-sheet-1-9/
You can find events on your own
Modify Mage.php in app folder
public static function dispatchEvent($name, array $data = array())
{
Varien_Profiler::start('DISPATCH EVENT:'.$name);
$result = self::app()->dispatchEvent($name, $data);
Varien_Profiler::stop('DISPATCH EVENT:'.$name);
//log your event
Mage::log("Event name is $name",null,'event.log');
return $result;
}
Do your action, like add item to cart, remove / update quantity and then check event.log in var/log

Related

In app billing milkman ane

Every time I am trying to use
AndroidIAB.androidIAB.consumeItem("coin_stack_2");
I get : failed:4040/The item 'coin_stack_2' was not previously loaded.
==> it's happening for all of my products that I'm trying to sell as a consumeItem
I have loaded the the function below at the start of the application :
AndroidIAB.androidIAB.loadPlayerInventory();
What am I doing wrong?
AndroidIAB.androidIAB.loadPlayerInventory is an asynchronous call, which means that you have to wait for it to finish. The full code should look similar to this:
// listen for inventory events
AndroidIAB.androidIAB.addEventListener(AndroidBillingEvent.INVENTORY_LOADED, onInventoryLoaded);
AndroidIAB.androidIAB.addEventListener(AndroidBillingErrorEvent.LOAD_INVENTORY_FAILED, onInventoryFailed);
function onInventoryLoaded(e:AndroidBillingEvent):void
{
for each(var purchase:AndroidPurchase in e.purchases)
{
trace("You own the item:"+purchase.itemId);
// this is where you'd update the state of your app to reflect ownership of the item
}
}
function onInventoryFailed(e:AndroidBillingErrorEvent):void
{
trace("Something went wrong loading inventory: "+e.text);
}
// load the player's current inventory
AndroidIAB.androidIAB.loadPlayerInventory();
In order to use consumeItem the user should purchase the item first and only than it is possible to use consumeItem

WinJS variable/object scope, settings, and events?

I am not sure what the proper heading / title for this question should be. I am new to WinJS and am coming from a .NET webform and winclient background.
Here is my scenario. I have a navigation WinJS application. My structure is:
default.html
(navigation controller)
(settings flyout)
pages/Home.html
pages/Page2.html
So at the top of the default.js file, it sets the following variables:
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var nav = WinJS.Navigation;
It seems like I cannot use these variables anywhere inside my settings flyout or any of my pages:ready functions. They are only scoped to the default.js?
In the same regard, are there resources on the interwebs (links) that show how to properly share variables, events, and data between each of my "pages"?
The scenario that I immediately need to overcome is settings. In my settings flyout, I read and allow the user to optionally set the following application setting:
var applicationData = Windows.Storage.ApplicationData.current;
var localSettings = applicationData.localSettings;
localSettings.values["appLocation"] = {string set by the user};
I want to respond to that event in either my default.js file or even one of my navigation pages but I don't know where to "listen". My gut is to listen for the afterhide event but how do I scope that back to the page where I want to listen from?
Bryan. codefoster here. If you move the lines you mentioned...
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var nav = WinJS.Navigation;
...up and out of the immediate function, they'll be in global scope and you'll have access to them everywhere. That's one of the first things I do in my apps. You'll hear warnings about using global scope, but what people are trying to avoid is the pattern of dropping everything in global scope. As long as you control what you put in there, you're fine.
So put them before the beginning of the immediate function on default.js...
//stuff here is scoped globally
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
var nav = WinJS.Navigation;
(function () {
//stuff here is scoped to this file only
})();
If you are saving some data and only need it in memory, you can just hang it off the app variable instead of saving it into local storage. That will make it available to the whole app.
//on Page2.js
app.myCustomVariable = "some value";
//on Page3.js
if(app.myCustomVariable == "some value") ...
Regarding your immediate need:
like mentioned in the other answer, you can use datachanged event.
Regards sharing variables:
If there are variables that you would like to keep global to the application, they can be placed outside the anonymous function like mentioned in the Jeremy answer. Typically, that is done in default.js. Need to ensure that scripts using the global variables are placed after the script defining the global variable - in default.html. Typically - such variable will point to singleton class. For example: I use it in one of my apps to store authclient/serviceclient for the backend service for the app. That way - the view models of the multiple pages need not create instance of the object or reference it under WinJS namespace.
WinJS has also concept of Namespace which lets you organize your functions and classes. Example:
WinJS.Namespace.define('Utils.Http',
{
stringifyParameters: function stringifyParameters(parameters)
{
var result = '';
for (var parameterName in parameters)
{
result += encodeURIComponent(parameterName) + '=' + encodeURIComponent(parameters[parameterName]) + '&';
}
if (result.length > 0)
{
result = result.substr(0, result.length - 1);
}
return result;
},
}
When navigating to a page using WinJS.Navigation.navigate, second argument initialState is available as options parameter to the ready event handler for the page. This would be recommended way to pass arguments to the page unless this it is application data or session state. Application data/session state needs to be handled separately and needs a separate discussion on its own. Application navigation history is persisted by the winjs library; it ensures that if the app is launched again after suspension - options will be passed again to the page when navigated. It is good to keep the properties in options object as simple primitive types.
Regards events:
Typically, apps consume events from winjs library. That can be done by registering the event handler using addEventListener or setting event properties like onclick etc. on the element. Event handlers are typically registered in the ready event handler for the page.
If you are writing your own custom control or sometimes in your view model, you may have to expose custom events. Winjs.UI.DOMEventMixin, WinJS.Utilities.createEventProperties can be mixed with your class using WinJS.Class.mix. Example:
WinJS.Class.mix(MyViewModel,
WinJS.Utilities.createEventProperties('customEvent'),
WinJS.UI.DOMEventMixin);
Most often used is binding to make your view model - observable. Refer the respective samples and api documentation for details. Example:
WinJS.Class.mix(MyViewModel,
WinJS.Binding.mixin,
WinJS.Binding.expandProperties({ items: '' }));
Here is what I ended up doing which is kinda of a combination of all the answers given:
Created a ViewModel.Settings.js file:
(function () {
"use strict";
WinJS.Namespace.define("ViewModel", {
Setting: WinJS.Binding.as({
Name: '',
Value: ''
}),
SettingsList: new WinJS.Binding.List(),
});
})();
Added that file to my default.html (navigation container page)
<script src="/js/VMs/ViewModel.Settings.js"></script>
Add the following to set the defaults and start 'listening' for changes
//add some fake settings (defaults on app load)
ViewModel.SettingsList.push({
Name: "favorite-color",
Value: "red"
});
// listen for events
var vm = ViewModel.SettingsList;
vm.oniteminserted = function (e) {
console.log("item added");
}
vm.onitemmutated = function (e) {
console.log("item mutated");
}
vm.onitemchanged = function (e) {
console.log("item changed");
}
vm.onitemremoved = function (e) {
console.log("item removed");
}
Then, within my application (pages) or my settings page, I can cause the settings events to be fired:
// thie fires the oniteminserted
ViewModel.SettingsList.push({
Name: "favorite-sport",
Value: "Baseball"
});
// this fires the itemmutated event
ViewModel.SettingsList.getAt(0).Value = "yellow";
ViewModel.SettingsList.notifyMutated(0);
// this fires the itemchanged event
ViewModel.SettingsList.setAt(0, {
Name: "favorite-color",
Value: "blue"
});
// this fires the itemremoved event
ViewModel.SettingsList.pop(); // removes the last item
When you change data that needs to be updated in real time, call applicationData.signalDataChanged(). Then in the places that care about getting change notifications, listen to the datachanged on the applicationData object. This is also the event that is raised when roaming settings are synchronized between computers.
I've found that many times, an instant notification (raised event) is unnecessary, though. I just query the setting again when the value is needed (in ready for example).

Dynamic Tabs and dynamic content from mySQL

Using CodeIgniter, I have a set of tabs with titles taken from a table on my DB.
When I click a certain tab, it loads a content which is also
from another table on my DB.
I know the second part will need something like ajax. But I'm really confused on how to do this in an MVC way.
I tried creating a controller which would fetch the title of the tabs from my model, then load a view passing the data fetch from my model as params. Now, I created the tab, but dynamically changing the content when clicked is where I'm stuck.
Anyone can at least tell me the basic idea on how to achieve this?
Thank you so much!
lets look at this example may be it will help you
Tab 1
Tab 2
Tab 3
Tab 4
// where $id is value on which you have to execute query anfdfetech data from DB
// here is JS function with ajax call
<script type="text/javascript">
function fetchdata(id){
$.ajax({
type:"POST", url:"<?php echo base_url()?>controllername/functionname,
data:"&id=" + id,
complete:function (data) {
alert(data.responseText);
//or here what you want to do with ajax response, like put content in any html tag
$('#htmlidoftag').html(data.responseText);//like this
}
});
}
</script>
// here is the php function within controller
function functionname()
{
// First, delete old captchas
$id= $_REQUEST['id']
$response = $this->model->model_function($id);
// in model function run your query to fetch data
echo $response ;
}

Primefaces PickList update target list on transfer

I want to update the lists in the bean when the user transfers an item from one list to another. Is there a way to do that?
Thx.
In the xhtml:
<p:pickList value="#{myBean.myDepartment}" onTransfer="handleTransfer(e)"....>
In the bean:
List<Department> selectedDepartments = new ArrayList<Department>();
List<Department> availableDepartments = getAvailableDepartments();
private DualListModel<Department> myDepartment;
myDepartment = new DualListModel<Department>(availableDepartments, selectedDepartments);
On Commit, Departments selected by the user can be accessed using selectedDepartments
And the script ...
<script type="text/javascript">
function handleTransfer(e) {
item = e.item;
alert(item.text());
fromList = e.from;
toList = e.to;
type = e.type; //type of transfer; command, dblclick or dragdrop)
}
</script>
I don't exactly know what do you want. This is done automatically same as if you type something into p:inputText it is available in beans property representing the value of p:inputText without need of manual update.
Just access the updated values in your pickList with getTarget() or getSource() methods. You are probably trying to access lists which you provided to DualListModel directly like:
DualListModel<fooType> fooModel = new DualListModel<fooType>(fooList1,fooList2);
// transfer item
// check if fooList2 is updated - this is wrong, it is **not** updated
fooModel.getTarget(); // this way you can get the actual values of target list
target - right side, source - left side of a pickList.

CakePHP - get last query run

I want to get the last query CakePHP ran. I can't turn debug on in core.php and I can't run the code locally. I need a way to get the last sql query and log it to the error log without effecting the live site. This query is failing but is being run.
something like this would be great:
$this->log($this->ModelName->lastQuery);
Thanks in advance.
For Cake 2.0, the query log is protected so this will work
function getLastQuery() {
$dbo = $this->getDatasource();
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
return $lastLog['query'];
}
Tested in CakePHP v2.3.2
$log = $this->Model->getDataSource()->getLog(false, false);
debug($log);
In CakePHP 1.x, the data you want is accessible in DataSource::_queriesLog. Cake doesn't really provide a getter method for this member, but the underlying language being PHP, nothing stops you from doing the following:
In app/app_model.php:
function getLastQuery()
{
$dbo = $this->getDatasource();
$logs = $dbo->_queriesLog;
return end($logs);
}
You can use this inline.
$dbo = $this->Model->getDatasource();
// store old state
$oldStateFullDebug = $dbo->fullDebug;
// turn fullDebug on
$dbo->fullDebug = true;
// Your code here! eg.
$this->Model->find('all');
// write to logfile
// use print_r with second argument to return a dump of the array
Debugger::log(print_r($dbo->_queriesLog, true));
// restore fullDebug
$dbo->fullDebug = $oldStateFullDebug;
Simple you can use showLog() function
var_dump($this->YourModel->getDataSource()->showLog());
This is a very late answer, i know, but for whoever needs this in the future, you can always restrict setting debug to your IP, For example:
Configure::write('debug', 0);
if($_SERVER["REMOTE_ADDR"] == '192.168.0.100'){
Configure::write('debug', 2); //Enables debugging only for your IP.
}
Combination of Matt's and blavia's solution (works when debug is not 2):
$dbo = $this->Model->getDatasource();
$oldStateFullDebug = $dbo->fullDebug;
$dbo->fullDebug = true;
// find or whatever...
$this->Model->find("all");
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
CakeLog::write("DBLog", $lastLog['query']);
$dbo->fullDebug = $oldStateFullDebug;
Having a quick skim of the book, cakephp api getLog you could turn on logTransaction. Although having not used it, I'm not sure how it will perform.
Otherwise you could experiment with FirePHP and here is the a guide for it,
You might try DebugKit, although off the top of my head I think you do still need debug 2 to get it to work.
Hopefully something might give you a lead. :)
You can use this:
$log = $this->Model->getDataSource()->getLog(false, false);
pr($log);die;
There are two methods to view the query in CakePHP.
Both methods you have to add the below one line in app/Config/core.php
Configure::write('debug', 2);
First methods :
debug($this->getLastQuery());
where you want to get the query add above line and call this function getLastQuery() on same controller using below code
public function getLastQuery() {
$dbo = $this->TModel->getDatasource(); //Here TModel is a model.what table you want to print
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
return $lastLog['query'];
}
second method :
add the below line in the any Elements files.
<?php echo $this->element('sql_dump'); ?>
This will help you.
echo '<pre>';
$log = $this->YOUR_MODEL->getDataSource();
print_r($log);
exit;