Say I have a quote from the admin create order with all the products already entered, how could I go about writing some code to add multiple shipping addresses and assign the item to the address.
Ive got some code working, based loosely off the frontend multiship model. The problem I'm having is adding the multiple address and assigning the items to the quote. If I have a standard quote, how can I add the multiple addresses?
I've already tried :
$address = Mage::getModel('customer/address')->load($addressID);
$quote->addShippingAddress($address);
Which seems to only hold one address
The whole function:
public function createMultiOrders() {
// print_r($_POST);
$items = $_POST['item'];
$itemsByAddress = array();
$billingInfo = array();
$session = Mage::getSingleton('adminhtml/session_quote');
$quote = $session->getQuote();
//first we are reorganizing the data provided by javascript into an array based on address ID's
foreach ($items as $key => $item) {
$addID = $item['addressID'];
$itemID = $key;
$qty = $item['qty'];
$itemsByAddress[$addID][] = array('itemID' => $itemID, 'qty' => $qty);
}
// print_r($itemsByAddress);
//now that we have an array of items, seperated by which addressid they goto, we can create the order for each address
foreach ($itemsByAddress as $addressID => $items) {
$address = Mage::getModel('customer/address')->load($addressID);
$quote->addShippingAddress($address);
echo"<br/>address id is $addressID, items are: <br/>";
foreach ($items as $item) {
// $address->addItem($_item);
///add items to order
// echo"id before is $item<br/>";
$itemID = explode('-_', $item['itemID']);
$itemID = $itemID[0];
$qty = $item['qty'];
echo "itemid is $itemID, qty is " . $qty . " <br/><br/><br/><br/>";
}
}
//print_r(get_class_methods($quote));
$shippingAddresses = $quote->getAllShippingAddresses();
try {
foreach ($shippingAddresses as $address) {
$order = $this->_prepareOrder($address);
$orders[] = $order;
Mage::dispatchEvent(
'checkout_type_multishipping_create_orders_single', array('order' => $order, 'address' => $address)
);
}
foreach ($orders as $order) {
$order->place();
$order->save();
if ($order->getCanSendNewEmailFlag()) {
$order->sendNewOrderEmail();
}
$orderIds[$order->getId()] = $order->getIncrementId();
}
Mage::getSingleton('core/session')->setOrderIds($orderIds);
Mage::getSingleton('checkout/session')->setLastQuoteId($quote->getId());
$quote->setIsActive(false)->save();
Mage::dispatchEvent('checkout_submit_all_after', array('orders' => $orders, 'quote' => $quote));
return $this;
} catch (Exception $e) {
Mage::dispatchEvent('checkout_multishipping_refund_all', array('orders' => $orders));
throw $e;
}
Ok I solved the issue and successfully was able to write a script to turn an ordinary admin order into a multi address order. One of the mistakes that messed with me the entire time was the way I loaded the admin quote:
I was loading the session like this
$session = Mage::getSingleton('adminhtml/session_quote');
and it should be
$session = Mage::getModel('adminhtml/session_quote');
Now, as far as assigning each of the quote items to an address, the final code looks like:
$address = Mage::getModel('customer/address')->load($addressID);
echo"<br/>address id is $addressID<br/>";
echo"quote address not set, adding shipping address <br/>";
$quoteAddress = Mage::getModel('sales/quote_address')->importCustomerAddress($address);
$quote->addShippingAddress($quoteAddress);
$quoteAddressItem = $quoteAddress->getItemByQuoteItemId($quoteItem->getId());
if ($quoteAddressItem) {
echo"increasing item quantitiy for quote address<br/>";
// $quoteAddressItem->setQty((int) ($quoteAddressItem->getQty() + $qty));
} else {
echo"setting customer id for quote item<br/>";
$quoteItem->setCustomerAddressId($quoteAddress->getCustomerAddressId());
echo"adding item to quote address<br/>";
$quoteAddress->addItem($quoteItem)->setQuote($quote);
echo"adding item to quote collection<br/>";
if (!$quoteAddress->getItemsCollection()->getItemById($quoteItem->getId())) {
$quoteAddress->getItemsCollection()->addItem($quoteItem)->save();
}
$quoteAddress->setCollectShippingRates(TRUE);
$quoteAddress->collectShippingRates();
$quoteAddress->save();
$quoteItem->save();
$quote->save();
}
Related
I would like to get product price with options price using a custom module that calculates product price by formula, i like to use the function without adding the product to the cart.
The function get a quote item paramter
public function getProductFinalPrice($item, $forReindex = false, $storeId = null)
So i thought about add a quote item with a info_buyRequest buy request
I tried this
$product = $this->_objectManager->create('Magento\Catalog\Model\Product')->load(5862);
$customOptions = $this->_objectManager->get('Magento\Catalog\Model\Product\Option')->getProductOptionCollection($product);
$item = $this->_objectManager->create('Magento\Quote\Model\Quote\Item');
$options = $this->_objectManager->get('Magento\Quote\Model\ResourceModel\Quote\Item\Collection');
$quote = $this->cart->getQuote();
$quote->addProduct($product);
$quote->save();
$options->setQuote($quote);
//$options->addItemFilter($item->getId());
$item->setQuote($quote)->setProduct($product)->setQty($qty);
foreach ($options as $option) {
$item->addOption($option);
}
$infoBuyRequest = [
"info_buyRequest" => [
"uenc" => "aHR0cHM6Ly93d3cud2V0YWcuY2EvZW5fY2EvbmFtZS10YWdzL25hbWUtdGFncy1pbnNwaXJhdGlvbi9jdXN0b20tbmFtZS10YWctb3JkZXIv",
"product" => 5862,
"qty" => $qty
]
];
$option = $this->_objectManager->create(
\Magento\Quote\Model\Quote\Item\Option::class,
['data' => $infoBuyRequest]
);
$item->addOption($option);
$item->setProductOptions($infoBuyRequest);
var_dump($this->_getBuyRequest($item));
var_dump($this->_getBuyRequest($item)); return
object(Magento\Framework\DataObject)#3647 (1) {
["_data":protected]=>
array(2) {
["original_qty"]=>
NULL
["qty"]=>
int(100)
}
}
I like to get something with info_buyrequest
[
"info_buyRequest" => [
"uenc" => "aHR0cHM6Ly93d3cud2V0YWcuY2EvZW5fY2EvbmFtZS10YWdzL25hbWUtdGFncy1pbnNwaXJhdGlvbi9jdXN0b20tbmFtZS10YWctb3JkZXIv",
"product" => 5862,
"qty" => $qty
]
]
This is the function _getBuyRequest
public function _getBuyRequest($item) {
$option = $item->getOptionByCode('info_buyRequest');
if ($option) {
$value = json_decode($option->getValue(), true); //in M2.2 json used for the buy request
if (is_null($value))
$value = unserialize($option->getValue()); //in M<2.2 the buy request is serialized
} else
$value = [];
$buyRequest = new \Magento\Framework\DataObject($value);
// Overwrite standard buy request qty, because item qty could have changed since adding to quote
$buyRequest->setOriginalQty($buyRequest->getQty())
->setQty($item->getQty() * 1);
return $buyRequest;
}
So how to add info_buyRequest? i would like to load options in the quote item.
foreach($quoteData->getAllVisibleItems() as $_item) {
print_r($_item->getBuyRequest());
}
Use this method $_item->getBuyRequest().
getBuyRequest already a method defined in quote model for info_buyRequest
I have developed simple application, i have generated checkbox in grid dynamically from database, but my problem is when user select the checkbox and other required field from grid and press submit button, it adds duplicate value, so i want to know how can i check the checkbox value & other field value with database value while submitting data to database.
following code i use to generate all selected items and then save too db
foreach ($this->addattendee->results as $key=>$value)
{
//print_r($value);
$id = $this->Attendee_model->save($value);
}
i am using codeigniter....can any one give the idea with sample code plz
{
$person = $this->Person_model->get_by_id($id)->row();
$this->form_data->id = $person->tab_classid;
$this->form_data->classtitle = $person->tab_classtitle;
$this->form_data->classdate = $person->tab_classtime;
$this->form_data->createddate = $person->tab_crtdate;
$this->form_data->peremail = $person->tab_pemail;
$this->form_data->duration = $person->tab_classduration;
//Show User Grid - Attendee>>>>>>>>>>>>>>>>>>>>>>>>
$uri_segment = 0;
$offset = $this->uri->segment($uri_segment);
$users = $this->User_model->get_paged_list($this->limit, $offset)->result();
// generate pagination
$this->load->library('pagination');
$config['base_url'] = site_url('person/index/');
$config['total_rows'] = $this->User_model->count_all();
$config['per_page'] = $this->limit;
$config['uri_segment'] = $uri_segment;
$this->pagination->initialize($config);
$data['pagination'] = $this->pagination->create_links();
// generate table data
$this->load->library('table');
$this->table->set_empty(" ");
$this->table->set_heading('Check', 'User Id','User Name', 'Email', 'Language');
$i = 0 + $offset;
foreach ($users as $user)
{
$checkarray=array('name'=>'chkclsid[]','id'=>'chkclsid','value'=>$user->user_id);
$this->table->add_row(form_checkbox($checkarray), $user->user_id, $user->user_name, $user->user_email,$user->user_language
/*,anchor('person/view/'.$user->user_id,'view',array('class'=>'view')).' '.
anchor('person/update/'.$user->user_id,'update',array('class'=>'update')).' '.
anchor('person/showattendee/'.$user->user_id,'Attendee',array('class'=>'attendee')).' '.
anchor('person/delete/'.$user->user_id,'delete',array('class'=>'delete','onclick'=>"return confirm('Are you sure want to delete this person?')"))*/ );
}
$data['table'] = $this->table->generate();
//end grid code
// load view
// set common properties
$data['title'] = 'Assign Attendees';
$msg = '';
$data['message'] = $msg;
$data['action'] = site_url('person/CreateAttendees');
//$data['value'] = "sssssssssssssssssss";
$session_data = $this->session->userdata('logged_in');
$data['username'] = "<p>Welcome:"." ".$session_data['username']. " | " . anchor('home/logout', 'Logout')." | ". "Userid :"." ".$session_data['id']; "</p>";
$data['link_back'] = anchor('person/index/','Back to list of Classes',array('class'=>'back'));
$this->load->view('common/header',$data);
$this->load->view('adminmenu');
$this->load->view('addattendee_v', $data);
}
The code is quite messy but I have solved a similar issue in my application I think, I am not sure if its the best way, but it works.
function save_vote($vote,$show_id, $stats){
// Check if new vote
$this->db->from('show_ratings')
->where('user_id', $user_id)
->where('show_id', $show_id);
$rs = $this->db->get();
$user_vote = $rs->row_array();
// Here we are check if that entry exists
if ($rs->num_rows() == '0' ){
// Its a new vote so insert data
$this->db->insert('show_ratings', $rate);
}else{
// Its a not new vote, so we update the DB. I also added a UNIQUE KEY to my database for the user_id and show_id fields in the show_ratings table. So There is that extra protection.
$this->db->query('INSERT INTO `show_ratings` (`user_id`,`show_id`,`score`) VALUES (?,?,?) ON DUPLICATE KEY UPDATE `score`=?;', array($user_id, $show_id, $vote, $vote));
return $update;
}
}
I hope this code snippet gives you some idea of what to do.
maybe i have same trouble with you.
and this is what i did.
<?php
public function set_news(){
$this->load->helper('url');
$slug = url_title($this->input->post('title'), 'dash', TRUE);
$query = $this->db->query("select slug from news where slug like '%$slug%'");
if($query->num_rows()>=1){
$jum = $query->num_rows() + 1;
$slug = $slug.'-'.$jum;
}
$data = array(
'title' => $this->input->post('title'),
'slug' => $slug,
'text' => $this->input->post('text')
);
return $this->db->insert('news', $data);
}
?>
then it works.
OK, below is a get_members function in my controller that I pulled and manipulated from the interwebs... i can print out the information from $output in the controller, but I don't want to do that... I cannot figure out how to get it to be part of my view so I can list info from it freely...
I know it has something to do with the $data array in the index function... can anyone assist?
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Phonedirectory extends CI_Controller {
function get_members($group=FALSE,$inclusive=FALSE) {
// Active Directory server
$ldap_host = "fps";
// Active Directory DN
$ldap_dn = "OU=Users,DC=xxx,DC=org";
// User attributes we want to keep
$keep = array(
"samaccountname",
"displayName",
"telephonenumber"
);
// Connect to AD
$ldap = ldap_connect($ldap_host) or die("Could not connect to LDAP");
ldap_set_option ($ldap, LDAP_OPT_REFERRALS, 0);
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_bind($ldap, "CN=LDAP Reader,OU=Users - Special,DC=xxx,DC=org", "xxx") or die("Could not bind to LDAP");
// Begin building query
if($group) $query = "(&"; else $query = "";
$query .= "(&(objectClass=user)(objectCategory=person))";
// Filter by memberOf, if group is set
if(is_array($group)) {
// Looking for a members amongst multiple groups
if($inclusive) {
// Inclusive - get users that are in any of the groups
// Add OR operator
$query .= "(|";
} else {
// Exclusive - only get users that are in all of the groups
// Add AND operator
$query .= "(&";
}
// Append each group
foreach($group as $g) $query .= "(memberOf=OU=$g,$ldap_dn)";
$query .= ")";
} elseif($group) {
// Just looking for membership of one group
$query .= "(memberOf=OU=$group,$ldap_dn)";
}
// Close query
if($group) $query .= ")"; else $query .= "";
// Uncomment to output queries onto page for debugging
// print_r($query);
// Search AD
$results = ldap_search($ldap,$ldap_dn,$query);
$entries = ldap_get_entries($ldap, $results);
// Remove first entry (it's always blank)
array_shift($entries);
$output = array(); // Declare the output array
$i = 0; // Counter
// Build output array
foreach($entries as $u) {
foreach($keep as $x) {
// Check for attribute
if(isset($u[$x][0])) $attrval = $u[$x][0]; else $attrval = NULL;
// Append attribute to output array
$output[$i][$x] = $attrval;
}
$i++;
}
return $output;
}
public function index() {
$data = array('title' => 'Phone Directory', 'main_content' => 'pages/phoneDirectory');
$this->load->view('template/main', $data);
}
}
Correct me if I'm wrong, but it sounds like you just want the output sent to the view?
If that's the case, then add this to the index function
public function index() {
$data = array('title' => 'Phone Directory', 'main_content' => 'pages/phoneDirectory');
$data['members'] = $this->get_members();
$this->load->view('template/main', $data);
}
or however you want to append that to your data array.
Then in the view you can do:
<?php echo print_r($members, TRUE); ?>
I get a request from an extrenal site containing some product ids.
In my module i try to load the products and add them to the shopping cart. I tried it with this code:
public function indexAction() {
$ids = explode(',', $this->getRequest()->getParam('products'));
Mage::log('ADDING PRODUCTS');
$cart = Mage::getModel('checkout/cart');
$cart->init();
$pModel = Mage::getSingleton('catalog/product');
//$cart->addProductsByIDs($ids);
foreach ($ids as $id) {
Mage::log('Loading: ' . $id);
$product = $pModel->load($id);
Mage::log('Loaded: ' . $product->getId());
try {
$cart->addProduct($product, array('qty' => '1'));
} catch (Exception $e) {
Mage::log($e);
continue;
}
}
$cart->save();
if ($this->getRequest()->isXmlHttpRequest()) {
exit('1');
}
$this->_redirect('checkout/cart');
}
I can see in the system.log that it loads the products correctly. But after the redirect i have the second product in my cart twice. The first one is missing. Using $cart->addProductsByIDs($ids) works great but then i cant influence the quantity of the products anymore.
Does someone know what i am doing wrong and give me a hint?
Thx
I had the same problem and I fixed it by loading the product model inside every loop:
public function AddMultipleItemsAction() {
$products = explode(',', $this->getRequest()->getParam('products'));
$quantities = explode(',', $this->getRequest()->getParam('quantities'));
$numProducts = count($products);
$cart = $this->_getCart();
for($i=0;$i<$numProducts;$i++) {
$product_id = $products[$i];
$quantity = $quantities[$i];
if ($product_id == '') continue;
if(!is_numeric($quantity) || $quantity <= 0) continue;
$pModel = Mage::getModel('catalog/product')->load($product_id);
if($pModel->getTypeId() == Mage_Catalog_Model_Product_Type::TYPE_SIMPLE) {
try {
$eventArgs = array(
'product' => $pModel,
'qty' => $quantity,
'additional_ids' => array(),
'request' => $this->getRequest(),
'response' => $this->getResponse(),
);
Mage::dispatchEvent('checkout_cart_before_add', $eventArgs);
$cart->addProduct($pModel, array('product'=>$product_id,'qty' => $quantity));
Mage::dispatchEvent('checkout_cart_after_add', $eventArgs);
Mage::dispatchEvent('checkout_cart_add_product', array('product'=>$pModel));
$message = $this->__('%s was successfully added to your shopping cart.', $pModel->getName());
Mage::getSingleton('checkout/session')->addSuccess($message);
} catch (Mage_Core_Exception $e) {
if (Mage::getSingleton('checkout/session')->getUseNotice(true)) {
Mage::getSingleton('checkout/session')->addNotice($pModel->getName() . ': ' . $e->getMessage());
}
else {
Mage::getSingleton('checkout/session')->addError($pModel->getName() . ': ' . $e->getMessage());
}
} catch (Exception $e) {
Mage::getSingleton('checkout/session')->addException($e, $this->__('Can not add item to shopping cart'));
}
}
}
$cart->save();
$this->_getSession()->setCartWasUpdated(true);
$this->_redirect('checkout/cart');
}
I then have an "Add all items to cart" button which executes the following Javascript code:
<script type="text/javascript">
function addAllItemsToCart() {
productsArr = new Array();
quantitiesArr = new Array();
$$('#product-listing-table .qty').each(
function (input, index) {
productsArr[index] = encodeURIComponent(input.readAttribute('product_id'));
quantitiesArr[index] = encodeURIComponent(input.value);
}
);
var url = '/MyModule/Cart/AddMultipleItems/products/'+productsArr.join(',')+'/quantities/'+quantitiesArr.join(',')+'/';
setLocation(url);
}
For this to be able to work, I put an extra product_id attribute on the quantity textbox, such as:
<input type="text" size="2" product_id="<?php echo $_product->getId();?>" name="productqty_<?php echo $_product->getId();?>" class="qty" />
and the whole list of products is inside a div with ID product-listing-table
Just checked with some custom add to cart code that I've got, and confirmed is working correctly, and the only difference I have is:
$cart->addProduct($product, array(
'qty' => 1,
'product' => $product->getId(),
'uenc' => Mage::helper('core')->urlEncode(Mage::helper('core/url')->getCurrentUrl())
));
// Also make sure we know that the cart was updated
Mage::getSingleton('checkout/session')->setCartWasUpdated(true);
That said, your error doesn't make it sound like you're actually having trouble in this area. I can't imagine it would be this, but is it possible that the cart model needs to be save()d every time you add a product to the cart? It's worth a punt.
I am working in a scenario I want to send Product selected Custom Option SKU in cart page have founded the array which is sent to cart in case of custom options.
Here is a Function called getProductOptions() in which Product Option Array is created and sent to cart. At this point, I want to send selected Custom Option SKU field to cart.
I have the following code:
public function getProductOptions()
{
$options = array();
if ($optionIds = $this->getItem()->getOptionByCode('option_ids')) {
$options = array();
foreach (explode(',', $optionIds->getValue()) as $optionId) {
if ($option = $this->getProduct()->getOptionById($optionId)) {
//echo $optionId;
echo "hhhhhhhhhhhhh";
//print_r( $option->getId());
//echo Mage::getModel('catalog/product')->getOptionSku($option);
//die();
//print_r( $option->getOptionSku());
//echo Mage_Catalog_Model_Product_Option_Type_Select::getOptionSku());
$quoteItemOption = $this->getItem()->getOptionByCode('option_' . $option->getId());
//echo $option->getQuoteItemOption($quoteItemOption);
$group = $option->groupFactory($option->getType())
->setOption($option)
->setQuoteItemOption($quoteItemOption);
$options[] = array(
'label' => $option->getTitle(),
'value' => $group->getFormattedOptionValue($quoteItemOption->getValue()),
'print_value' => $group->getPrintableOptionValue($quoteItemOption->getValue()),
'option_id' => $option->getId(),
'option_type' => $option->getType(),
'custom_view' => $group->isCustomizedView(),
'option_sku'=>//What should i call here to send Selected option SKU to this Array
);
}
}
if ($addOptions = $this->getItem()->getOptionByCode('additional_options')) {
$options = array_merge($options, unserialize($addOptions->getValue()));
}
}
return $options;
}
It looks like the bit you're missing is
'option_sku' => $this->getItem()->getSku()
Don't modify the block itself, just change the rendered template to add a for this field. Grab the data from the $_item variable, and echo it out to the user. That should require no modifications of the block.