I am try to create an additional step in the Magento onepage checkout process.
I am following the tutorial located at http://www.excellencemagentoblog.com/magento-onestep-checkout-add-step but specifically adding a step at the end before the review.
My folder / file structure is as follows. (Ignore widget.xml)
I have uploaded the code in it's current state to this gist:
https://gist.github.com/Relequestual/5263498
I have the theme set to 'new'.
I am var_dumping the $this->getSteps() which shows that the 'testcheck' returns null.
In config.xml, if I change under gobal, blocks, checkout, rewrite, onepage to the same class with '_TestCheck' on the end, the checkout doesn't display at all, but 'Test Check' appears in the progress section on the right. When I revert this change, it then shows as not being null in the var dump like so...
But, I still don't see the step actually added to the page.
I've not done any magento before, so feel a bit in over my head. I expect there is some problem with the xml configuration files, but I've been working on this for 2 days now, and am somewhat lost as to what else I can try.
I know this question may sound similar to others, which it is, however I can't find a question where the OP has the same symptoms as what I am seeing.
By default magento gives some checkout steps. But Sometime you need to add extra information from the customer for future reference. A common requested customization is to add the Custom Form in default checkout process.
This is not good practice to touch core files. You can do this via overriding Modules.
In this example Comapnyname is Ipragmatech and Module name is Checkoutstep.
Step1: Add Custom step in the checkout process
Open the Ipragmatech > Checkoutstep > Block > Onepage> Checkoutstep.php file and write the following code
class Ipragmatech_Checkoutstep_Block_Onepage_Checkoutstep extends Mage_Checkout_Block_Onepage_Abstract
{
protected function _construct()
{
$this->getCheckout()->setStepData('checkoutstep', array(
'label' => Mage::helper('checkout')->__('Invitation to participation'),
'is_show' => true
));
parent::_construct();
}
}
Step2: Add steps which and where you want in the checkout process
Open the Ipragmatech > Checkoutstep > Block > Onepage> Checkoutstep.php file and write the following code
class Ipragmatech_Checkoutstep_Block_Onepage extends Mage_Checkout_Block_Onepage
{
public function getSteps()
{
$steps = array();
if (!$this->isCustomerLoggedIn()) {
$steps['login'] = $this->getCheckout()->getStepData('login');
}
$stepCodes = array('billing', 'shipping', 'shipping_method', 'payment', 'checkoutstep', 'review');
foreach ($stepCodes as $step) {
$steps[$step] = $this->getCheckout()->getStepData($step);
}
return $steps;
}
}
Step3: Grab the submitted value of custom form and set the values of Custom form
Open the ipragmatech > Checkoutstep > controllers > OnepageController.php and write the following fucntion
public function saveCheckoutstepAction()
{
$this->_expireAjax();
if ($this->getRequest()->isPost()) {
//Grab the submited value
$_entrant_name = $this->getRequest()->getPost('entrant_name',"");
$_entrant_phone = $this->getRequest()->getPost('entrant_phone',"");
$_entrant_email = $this->getRequest()->getPost('entrant_email',"");
$_permanent_address = $this->getRequest() ->getPost('permanent_address',"");
$_address = $this->getRequest()->getPost('local_address',"");
Mage::getSingleton('core/session') ->setIpragmatechCheckoutstep(serialize(array(
'entrant_name' =>$_entrant_name,
'entrant_phone' =>$_entrant_phone,
'entrant_email' =>$_entrant_email,
'permanent_address' =>$_permanent_address,
'address' =>$_address
)));
$result = array();
$redirectUrl = $this->getOnePage()->getQuote()->getPayment() ->getCheckoutRedirectUrl();
if (!$redirectUrl) {
$this->loadLayout('checkout_onepage_review');
$result['goto_section'] = 'review';
$result['update_section'] = array(
'name' => 'review',
'html' => $this->_getReviewHtml()
);
}
if ($redirectUrl) {
$result['redirect'] = $redirectUrl;
}
$this->getResponse()->setBody(Zend_Json::encode($result));
}
}
Step4: Save Custom Form information
When checkout_onepage_controller_success_action
event hook is called. Open the Ipragmatech > Checkoutstep > Model >Observer.php and write the following
class Ipragmatech_Checkoutstep_Model_Observer {
const ORDER_ATTRIBUTE_FHC_ID = 'checkoutstep';
public function hookToOrderSaveEvent() {
if (Mage::helper('checkoutstep')->isEnabled()) {
$order = new Mage_Sales_Model_Order ();
$incrementId = Mage::getSingleton ( 'checkout/session' )->getLastRealOrderId ();
$order->loadByIncrementId ( $incrementId );
// Fetch the data
$_checkoutstep_data = null;
$_checkoutstep_data = Mage::getSingleton ( 'core/session' )->getIpragmatechCheckoutstep ();
$model = Mage::getModel ( 'checkoutstep/customerdata' )->setData ( unserialize ( $_checkoutstep_data ) );
$model->setData ( "order_id",$order["entity_id"] );
try {
$insertId = $model->save ()->getId ();
Mage::log ( "Data successfully inserted. Insert ID: " . $insertId, null, 'mylog.log');
} catch ( Exception $e ) {
Mage::log ( "EXCEPTION " . $e->getMessage (), null, 'mylog.log' );
}
}
}
}
Magento – Add Custom Form in Checkout Extension is a complete solution to add extra step in Checkout process for your ecommerce website. It allow admin to export data from custom table in CSV format.
Visit the link to get this free extension http://www.magentocommerce.com/magento-connect/custom-form-in-checkout.html
Related
we have a services woocommerce online shop with three shop managers.
We would like to filter new orders and assign them to one of these three managers. The managers only can see their assigned orders, and can't access or see the rest.
Maybe this could be done by filtering the backend view (admin panel) via custom_field, but I don't know if it is a good approach. Maybe there is a plugin based on role capabilites.
Any suggest?
Thanks.
After having the same issue I combined the solutions of similar, already answered questions and it worked. I know the question is old, but someone may find it helpful. Here is one possible solution:
Add custom meta key containing your desired store_manager id to every order (in my case if a order was from a specific country I wanted only a sprecific store_manager to see it, you can put your custom logic in the before_checkout_create_order() function)
function before_checkout_create_order($order, $data) {
$country = $order->billing_country;
$store_manager_id = '';
$belgium_region = ['BE', 'NL', 'DE'];
$czech_region = ['CZ', 'AT', 'SI', 'HU'];
$uk_region = ['GB'];
if (in_array($country, $belgium_region)) {
// Manually assigning the _store_manager_id using the user id, yours will differ
$store_manager_id = 7;
} else if (in_array($country, $czech_region)) {
$store_manager_id = 3;
} else if (in_array($country, $uk_region)) {
$store_manager_id = 2;
} else {
$store_manager_id = 1;
}
$order->update_meta_data('_store_manager_id', $store_manager_id);
}
add_action('woocommerce_checkout_create_order', 'before_checkout_create_order', 20, 2);
I found the method for assigning custom meta keys to a order ON THIS THREAD you can see what the woocommerce_checkout_create_order and $order->update_meta_data() hook and method do there, it's already greatly explained by its author
Filter the Woocommerce Admin Order list to only show current user assigned orders (but let Master Admin view all orders also)
function custom_admin_shop_manager_orders($query) {
global $pagenow;
$qv = &$query->query_vars;
$currentUserRoles = wp_get_current_user()->roles;
$user_id = get_current_user_id();
if (in_array('shop_manager', $currentUserRoles)) {
if ( $pagenow == 'edit.php' &&
isset($qv['post_type']) && $qv['post_type'] == 'shop_order' ) {
// I use the meta key from step 1 as a second parameter here
$query->set('meta_key', '_store_manager_id');
// The value we want to find is the $user_id defined above
$query->set('meta_value', $user_id);
}
}
return $query;
}
add_filter('pre_get_posts', 'custom_admin_shop_manager_orders');
As you can see we check if the current user role is shop_manager so all the logic after that doesn't count if you're the admin - you will see all the orders, but if you are a shop_manager you will get only your orders. The edit.php is the woocommerce orders list page.
I found the second step in THIS THREAD so you can found more info there also.
Hope this helps you!
This function makes the orders display only to its own authors (shop managers):
function alter_the_edit_screen_query( $wp_query ) {
if ( ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php' ) !== false ) and ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php?post_type=unit' ) === false ) and ( strpos( $_SERVER[ 'REQUEST_URI' ], '/wp-admin/edit.php?post_type=course' ) === false ) ) {
if ( !current_user_can( 'activate_plugins' ) ) {
add_action( 'views_edit-post', 'remove_items_from_edit' );
global $current_user;
$wp_query->set( 'author', $current_user->id );
}
}
}
add_filter('parse_query', 'alter_the_edit_screen_query' );
function remove_items_from_edit( $views ) {
unset($views['all']);
unset($views['publish']);
unset($views['trash']);
unset($views['draft']);
unset($views['pending']);
return $views;
}
This other function hides "All orders" tab to no-admin users (as shop manager):
function my_custom_admin_head() {
if ( ! current_user_can( 'update_core' ) ) {
echo '<style type="text/css">
ul.subsubsub li.all { display:none!important; }
</style>';
}
}
add_action( 'admin_head', 'my_custom_admin_head' );
In my CE-1.9.0 store my products currently create the following url rewrites:
http://example.com/product-name
http://example.com/category/product-name
http://example.com/another-category/subcategory/product-name
However in my store I want to be able to stop creating the rewrites for the category versions. I have System > Configuration > Catalog > Catalog > Use Categories Path for Product URLs set to No so these extra rewrites are unnecessary. Plus my store has around 500,000 products and counting so these extra url's are taking up a lot of space in the core_url_rewrite` table.
So my aim is to only be left with these versions:
http://example.com/product-name
If I truncate the core_url_rewrite table and reindex then only these versions get created so it is only when new products are created. My catalog is so large so I cannot keep truncated and rebuilding the table from scratch as the rebuilding takes several hours.
With help from this question I have found the file that is responsible for creating the rewrites when a product is created. It is:
app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php
However the answer is no longer valid as the code has changed in the core file.
In this file on line #538 there is the _afterLoad function it is the line
$this->_addUrlRewrite($this->_urlRewriteCategory);
And this function _addUrlRewrite however i've tried changing a lot inside this function but have had no luck. The function in full is:
protected function _addUrlRewrite()
{
$urlRewrites = null;
if ($this->_cacheConf) {
if (!($urlRewrites = Mage::app()->loadCache($this->_cacheConf['prefix'] . 'urlrewrite'))) {
$urlRewrites = null;
} else {
$urlRewrites = unserialize($urlRewrites);
}
}
if (!$urlRewrites) {
$productIds = array();
foreach($this->getItems() as $item) {
$productIds[] = $item->getEntityId();
}
if (!count($productIds)) {
return;
}
$select = $this->_factory->getProductUrlRewriteHelper()
->getTableSelect($productIds, $this->_urlRewriteCategory, Mage::app()->getStore()->getId());
$urlRewrites = array();
foreach ($this->getConnection()->fetchAll($select) as $row) {
if (!isset($urlRewrites[$row['product_id']])) {
$urlRewrites[$row['product_id']] = $row['request_path'];
}
}
if ($this->_cacheConf) {
Mage::app()->saveCache(
serialize($urlRewrites),
$this->_cacheConf['prefix'] . 'urlrewrite',
array_merge($this->_cacheConf['tags'], array(Mage_Catalog_Model_Product_Url::CACHE_TAG)),
$this->_cacheLifetime
);
}
}
foreach($this->getItems() as $item) {
if (empty($this->_urlRewriteCategory)) {
$item->setDoNotUseCategoryId(true);
}
if (isset($urlRewrites[$item->getEntityId()])) {
$item->setData('request_path', $urlRewrites[$item->getEntityId()]);
} else {
$item->setData('request_path', false);
}
}
}
I'm attempting to add a very basic (literally just a div with some text and a continue button) step to the onepage checkout but have come up short, in that they don't work (i suspect it's because they were created prior to 1.7.0.2), when following the examples here (Fontis), here (inchoo) and here (Magento Forums).
I've also tried to combined bits from different examples and forum posts but i've gotten no where in the week i've been attempting to do this.
I have been recommended the book 'Php Architect's Guide to E-Commerce Programming with Magento' which i've purchased and will begin reading but i was wondering if someone could kindly point me in the right direction in adding a new step to 1.7.0.2's onepage checkout?
Much appreciated for any help!
I have done this successfully in 1.7.0.2 following this guide:
http://www.excellencemagentoblog.com/magento-onestep-checkout-add-step
In summary, you need to extend/override Mage_Checkout_Block_Onepage::getSteps() to add your new step in the sequence.
Create your new step's block/template (loaded using an Ajax request when the previous step is completed) Your block class will need to extend: Mage_Checkout_Block_Onepage_Abstract
You also need to extend the onepagecheckout javascript as this does much of the heavy lifting. The Prototype library has a nice way of doing this.
Finally you will need to extend the controller class (Mage_Checkout_OnepageController) to override the responses of any existing steps, return the content of your new step (loaded using ajax), and handle the save action of any data (form fields etc) entered in your new step.
By default magento gives some checkout steps. But Sometime you need to add extra information from the customer for future reference. A common requested customization is to add the Custom Form in default checkout process.
This is not good practice to touch core files. You can do this via overriding Modules.
In this example Comapnyname is Ipragmatech and Module name is Checkoutstep.
Step1: Add Custom step in the checkout process
Open the Ipragmatech > Checkoutstep > Block > Onepage> Checkoutstep.php file and write the following code
class Ipragmatech_Checkoutstep_Block_Onepage_Checkoutstep extends Mage_Checkout_Block_Onepage_Abstract
{
protected function _construct()
{
$this->getCheckout()->setStepData('checkoutstep', array(
'label' => Mage::helper('checkout')->__('Invitation to participation'),
'is_show' => true
));
parent::_construct();
}
}
Step2: Add steps which and where you want in the checkout process
Open the Ipragmatech > Checkoutstep > Block > Onepage> Checkoutstep.php file and write the following code
class Ipragmatech_Checkoutstep_Block_Onepage extends Mage_Checkout_Block_Onepage
{
public function getSteps()
{
$steps = array();
if (!$this->isCustomerLoggedIn()) {
$steps['login'] = $this->getCheckout()->getStepData('login');
}
$stepCodes = array('billing', 'shipping', 'shipping_method', 'payment', 'checkoutstep', 'review');
foreach ($stepCodes as $step) {
$steps[$step] = $this->getCheckout()->getStepData($step);
}
return $steps;
}
}
Step3: Grab the submitted value of custom form and set the values of Custom form
Open the ipragmatech > Checkoutstep > controllers > OnepageController.php and write the following fucntion
public function saveCheckoutstepAction()
{
$this->_expireAjax();
if ($this->getRequest()->isPost()) {
//Grab the submited value
$_entrant_name = $this->getRequest()->getPost('entrant_name',"");
$_entrant_phone = $this->getRequest()->getPost('entrant_phone',"");
$_entrant_email = $this->getRequest()->getPost('entrant_email',"");
$_permanent_address = $this->getRequest() ->getPost('permanent_address',"");
$_address = $this->getRequest()->getPost('local_address',"");
Mage::getSingleton('core/session') ->setIpragmatechCheckoutstep(serialize(array(
'entrant_name' =>$_entrant_name,
'entrant_phone' =>$_entrant_phone,
'entrant_email' =>$_entrant_email,
'permanent_address' =>$_permanent_address,
'address' =>$_address
)));
$result = array();
$redirectUrl = $this->getOnePage()->getQuote()->getPayment() ->getCheckoutRedirectUrl();
if (!$redirectUrl) {
$this->loadLayout('checkout_onepage_review');
$result['goto_section'] = 'review';
$result['update_section'] = array(
'name' => 'review',
'html' => $this->_getReviewHtml()
);
}
if ($redirectUrl) {
$result['redirect'] = $redirectUrl;
}
$this->getResponse()->setBody(Zend_Json::encode($result));
}
}
Step4: Save Custom Form information
When checkout_onepage_controller_success_action
event hook is called. Open the Ipragmatech > Checkoutstep > Model >Observer.php and write the following
class Ipragmatech_Checkoutstep_Model_Observer {
const ORDER_ATTRIBUTE_FHC_ID = 'checkoutstep';
public function hookToOrderSaveEvent() {
if (Mage::helper('checkoutstep')->isEnabled()) {
$order = new Mage_Sales_Model_Order ();
$incrementId = Mage::getSingleton ( 'checkout/session' )->getLastRealOrderId ();
$order->loadByIncrementId ( $incrementId );
// Fetch the data
$_checkoutstep_data = null;
$_checkoutstep_data = Mage::getSingleton ( 'core/session' )->getIpragmatechCheckoutstep ();
$model = Mage::getModel ( 'checkoutstep/customerdata' )->setData ( unserialize ( $_checkoutstep_data ) );
$model->setData ( "order_id",$order["entity_id"] );
try {
$insertId = $model->save ()->getId ();
Mage::log ( "Data successfully inserted. Insert ID: " . $insertId, null, 'mylog.log');
} catch ( Exception $e ) {
Mage::log ( "EXCEPTION " . $e->getMessage (), null, 'mylog.log' );
}
}
}
}
Magento – Add Custom Form in Checkout Extension is a complete solution to add extra step in Checkout process for your ecommerce website. It allow admin to export data from custom table in CSV format.
Visit the link to get this free extension http://www.magentocommerce.com/magento-connect/custom-form-in-checkout.html
I am trying to create a new shipping method. This method allows users to COLLECT items from a paticular warehouse. So not much involved really.
I have followed a couple of tuts online, and have my module built and installed. It is working on the backend, i can enAble it, and set various values.
When i use the frontend checkout....or even use the following code:
Mage::getSingleton('shipping/config')->getAllCarriers();
I do not get the new shipping method name output.
The message i get on the frontend checkout is:
Sorry, no quotes are available for this order at this time.
Even though i have other shipping methods enabled.
I have another extension in use (regarding stock located in several warehouses). As part of this extension, it lists available shipping options...so that i can assign specific options to a specific warehouse. My new shipping method is not listed that shipping options list.
I seem to have everything required. My other extension is not picking up the method...so must be missing something.
Also, given i am getting no shipping options on frontend...confusing.
I was creating a complex shipping method...rather than a copy of the free shipping method. Turns out i actually needed a copy of the free shipping method, so made my life easier...
This was easier than i thought it would be.
Dont want to post all my code (you will also need a config.xml and system.xml file) but heres my carrier model logic file:
class Myco_Clickcollectshipping_Model_Carrier_Mymethod extends Mage_Shipping_Model_Carrier_Abstract {
protected $_code = 'mymethod ';
public function collectRates(Mage_Shipping_Model_Rate_Request $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
$freeBoxes = 0;
if ($request->getAllItems()) {
foreach ($request->getAllItems() as $item) {
if ($item->getFreeShipping() && !$item->getProduct()->isVirtual()) {
$freeBoxes+=$item->getQty();
}
}
}
$this->setFreeBoxes($freeBoxes);
$result = Mage::getModel('shipping/rate_result');
if ($this->getConfigData('type') == 'O') { // per order
$shippingPrice = $this->getConfigData('price');
} elseif ($this->getConfigData('type') == 'I') { // per item
$shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price'));
} else {
$shippingPrice = false;
}
$shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice);
if ($shippingPrice !== false) {
$method = Mage::getModel('shipping/rate_result_method');
$method->setCarrier('mymethod ');
$method->setCarrierTitle($this->getConfigData('title'));
$method->setMethod('mymethod ');
$method->setMethodTitle($this->getConfigData('name'));
if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) {
$shippingPrice = '0.00';
}
$method->setPrice($shippingPrice);
$method->setCost($shippingPrice);
$result->append($method);
}
return $result;
}
public function getAllowedMethods()
{
return array('mymethod ' => $this->getConfigData('name'));
}
}
I generate a Sitemap using Zend_Navigation and i wanted to add images to this sitemap, now i got no Idea how to get this done, i use following (working) code to generate the sitemap
foreach($sitemapItems as $item)
{
$newSite = new Zend_Navigation_Page_Uri();
$newSite->uri = 'http://' . $_SERVER['HTTP_HOST'] . $item->getSpeakingUrl();
$newSite->lastmod = $item->getUpdatedAt();
$newSite->changefreq = 'weekly';
$this->_navigation->addPage($newSite);
}
$this->view->navigation($this->_navigation);
$this->view->navigation()->sitemap()->setFormatOutput(true);
The Output is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>http://test.dev/pictures/site-28.html</loc>
<lastmod>2010-03-11T17:47:30+01:00</lastmod>
<changefreq>weekly</changefreq>
</url>
....
I need the following Output inside the Url part
<image:image>
<image:loc>http://example.com/image.jpg</image:loc>
</image:image>
i tried to just set
$newSite->image = URI
but it didnt work also i tried to add custom attribute via
$newSite->__set('image', array('loc' => URI));
Does anyone know if what i want is even possible ? i cant find anything in the docs or web...
Thanks for your time,
Dominik
Oki so first what you need to do is extend Zend_Navigation_Page_Uri and add you're image var to it smth like below :
class Mylib_NavPageUriImage extends Zend_Navigation_Page_Uri
{
protected $_image = null;
public function setImage($image)
{
if (null !== $image && !is_string($image)) {
require_once 'Zend/Navigation/Exception.php';
throw new Zend_Navigation_Exception(
'Invalid argument: $image must be a string or null');
}
$this->_image = $image;
return $this;
}
public function getImage()
{
return $this->_image;
}
public function toArray()
{
return array_merge(
parent::toArray(),
array(
'image' => $this->getImage()
));
}
}
Add this class to library/Mylib/NavPageUriImage.php.
To make it usable you need to register the namespace ( i like to register my namespaces at bootstrap but it can be done from app.ini too ) so in you're bootstrap class add the following :
function _initNamespace()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('Mylib_');
}
Then in you're controller you can now use :
$newSite = new Mylib_NavPageUriImage();
$newSite->uri = 'http://' . $_SERVER['HTTP_HOST'] . $item->getSpeakingUrl();
$newSite->lastmod = $item->getUpdatedAt();
$newSite->changefreq = 'weekly';
$newSite->image = 'some image';
THE FOLLOWING IS NOT RECOMENDED , YOU NEED TO EXTEND YOU'RE OWN NAVIGATION HELPER AND USE THAT ( i just don't have the time to play with it now ) ALLSO ADD YOU'RE OWN imageValidator
And then in library/zend/view/helper/navigation/sitemap.php add the following lines ( under the add priority element if statement , mine ends at 443 so i added this at 444 ) :
// add 'image' element if a valid image is set in page
if (isset($page->image)) {
$image = $page->image;
$imgDom = $dom->createElementNS(self::SITEMAP_NS, 'image:image');
$imgDom->appendChild($dom->createElementNS(self::SITEMAP_NS, 'image:loc', $image));
$urlNode->appendChild($imgDom);
}