I want to catch all placed order with an observer to use the data in a further process.
In my Observer I wrote:
class Custom_CrmApi_Model_Observer extends Varien_Object {
….
public function placeOrder( $observer ){
$order = $observer->getOrder();
$payment = $order->getPayment();
$transId = $order->getPayment()->getTransactionId();
//$transId = $order->getPayment()->getLastTransId();
....
But the transaction ID of all ebay orders is empty (but not in the backend). I am using the M2E extension for ebay integration. But that shouldn’t be the problem, because the observer catch any placed order, or? At this time the transaction Id supposed to be available. But for some reason it isn’t available.
Any ideas? Perhaps a work around?
Thank you so much in advanced,
Hannes
It may be too late for you but maybe works for someone else.
I used this code to get the Transaction id for my report. It is on a different place then the normal ones for m2epro orders.
$additional_data = $order->getPayment()->getData();
//print_r($additional_data['additional_data']);
$component_mode = $additional_data['additional_data'];
additional_data in payment gives you the information about the transaction.
I am getting channel, payment, channel_order_id, channel_final_fee, transaction_id, fee, sum and transaction_date from aditional_data of the order. It is possible to get the same data from the same place on placeOrder function in m2epro.
app\code\community\Ess\M2ePro\Model\Magento\Order.php -> placeOrder
if (version_compare(Mage::helper('M2ePro/Magento')->getVersion(false), '1.4.1', '>=')) {
/** #var $service Mage_Sales_Model_Service_Quote */
$service = Mage::getModel('sales/service_quote', $this->quote);
$service->submitAll();
// You can get this order before you return it and get the data maybe!
return $service->getOrder();
}
Worths to try.
Cheers
Related
So I've run into this issue a few times and now I've decided that I want to find a better solution.
For examples sake, I have two models, Order & Product. There is a many to many relation so that an order can have multiple products and a product can of course have multiple orders. Table structure looks like the below -
orders
id
more fields...
products
id
more fields...
product_orders
order_id
product_id
So when an order is created I run the following -
$order = Order::create($request->validated())
$order->products()->attach([1,2,3,4...]);
So this creates an order and attaches the relevant products to it.
However, I want to use an observer, to determine when the order is created and send out and perform related tasks off the back (send an order confirmation email, etc.) The problem being, at the time the order created observer is triggered, the products aren't yet attached.
Is there any way to do the above, establishing all the many to many relationships and creating the order at the same time so I can access linked products within the Order created observer?
Use case 1
AJAX call hits PUT /api/order which in turn calls Order::place() method. Once an order is created, an email is sent to the customer who placed the order. Now I could just put an event dispatch within this method that in turn triggers the email send but this just feels a bit hacky.
public static function place (SubmitOrderRequest $request)
{
$order = Order::create($request->validated());
$order->products()->attach($request->input('products'));
return $order;
}
Use case 2
I'm feature testing to make sure that an email is sent when an order is created. Now, this test passes (and email sends work), but it's unable to output the linked products at this point in execution.
/**
* #test
**/
public function an_email_is_sent_on_order_creation()
{
Mail::fake();
factory(Order::class)->create();
Mail::assertSent(OrderCreatedMailable::class);
}
Thanks,
Chris.
I think the solution to your problem could be transaction events as provided by this package from fntneves.
Personally, I stumbled upon the idea of transactional events for another reason. I had the issue that my business logic required the execution of some queued jobs after a specific entity had been created. Because my entities got created in batches within a transaction, it was possible that an event was fired (and the corresponding event listener was queued), although the transaction was rolled back because of an error shortly after. The result were queued listeners that always failed.
Your scenario seems comparable to me as you don't want to execute your event listeners immediately due to missing data which is only attached after the model was actually created. For this reason, I suggest wrapping your order creation and all other tasks that manipulate the order within a transaction. Combined with the usage of said package, you can then fire the model created event as the actual event listener will only be called after the transaction has been committed. The code for all this basically comes down to what you already described:
DB::transaction(function() {
$order = Order::create($request->validated());
$order->products()->attach($request->input('products'));
});
In your model, you'd simply define an OrderCreated event or use an observer as suggested in the other answer:
class Order
{
protected $dispatchesEvents = [
'created' => OrderCreated::class,
];
}
class OrderCreated implements TransactionalEvent
{
public $order;
/**
* Create a new event instance.
*
* #param \App\Order $order
* #return void
*/
public function __construct(Order $order)
{
$this->order = $order;
}
}
You can redefine boot method in your model, if product ids is static
class Order extends Eloquent {
protected static function boot() {
parent::boot();
static::saving(function ($user) {
$this->products()->attach([1,2,3,4...]);
});
}
}
Or use observers
class OrderObserver
{
public function created($model)
{
//
}
}
And register this
class EventServiceProvider extends ServiceProvider
{
public function boot(DispatcherContract $events)
{
parent::boot($events);
Order::observe(new OrderObserver());
}
}
I am trying to build a Magento module that observes certain events and tries to proceed automatically to a new automatic status/state, based on payment method.
In order to do that, I organized some status on the backoffice based on payment method. For example:
event: sales_order_place_after
Automatic status: pp_1_pending - First status/state where a new placed order will automatically have this status if the payment method is paypal.
event: sales_order_payment_pay
Automatic status: pp_2_payment - Second status/state after an order is payed when the payment method is paypal
event: sales_order_invoice_save_after
Automatic status: pp_3_complete- Third and final status/state after an order is invoiced, ending the transaction.
For this to work I would need to collect all status with the prefix pp_ and after checking which was set on the order, proceed to the next status in order. This way this module would be scalable.
However I can't seem to get the status collection. I am trying:
$statuses = Mage::getModel('sales/order_status')
->getCollection()
->addAttributeToSelect('status')
->addAttributeToSelect('label')
->addFieldToFilter('status',array('like','pp_'));
Hope anyone can help me. Thanks all!
The addAttributeToSelect() function is used for EAV based models.For flat models use addFieildToSelect()
The code should be
$statuses = Mage::getModel('sales/order_status')
->getCollection()
->addFieldToSelect('status')
->addFieldToSelect('label')
->addFieldToFilter('status',array('like'=>'pp_%'));
Have a look at the generated SELECT query if it looks ok.
$collection->getSelect()->__toString();
you have to use the wildcard (%) in your query, because you want the statuses that begin with pp_:
$statuses = Mage::getModel('sales/order_status')
->getCollection()
->addAttributeToSelect('status')
->addAttributeToSelect('label')
->addFieldToFilter('status',array('like','pp_%'));
in case someone is wondering, to get both states and status together, here's a function for you:
private function _allStatusStateCollection($filter) {
$collection = Mage::getModel( 'sales/order_status' )
->getCollection()->joinStates();
if ($filter != '') { return $collection->addFieldToFilter('main_table.status',array('like'=>$filter.'%')); }
return $collection;
}
I am well aware of finding out the number of times a coupon code was used (salesrule/coupon model). However, I would like to know how to intercept the use of a coupon and record its grand total in a table.
I have tried to do this by overriding the successAction() method of the Mage_Checkout_OnepageController, however if I try to get the coupon code with
$couponCode = (string) Mage::getSingleton('checkout/cart')->getQuote()->getCouponCode();
$couponCode turns out to be a blank string. It would seem that, by the time the successAction is called, the checkout/cart singleton has already been emptied. How can I intercept the 'place order' button and still be able to get the coupon code the customer used?
All help is greatly appreciated and I always accept an answer!
Upon entry of the successAction the _quote property of the checkout/cart object is already nullified.
However, you still can get your data upon entry of the successAction by using:
$oOrder = Mage::getModel('sales/order')
->load($this->getOnePage()->getCheckout()->getLastOrderId());
var_dump(
$oOrder->getCouponCode(),
$oOrder->getDiscountAmount(),
$oOrder->getGrandTotal()
);
But I'd recommend to create an observer for the checkout_onepage_controller_success_action event instead. This way you don't have to override anything at all. And usually nothing to maintain when it comes to Magento upgrades.
The code of such observer would look similiar like this:
/**
* checkout_onepage_controller_success_action event observer
*
* #param object $oObserver
* #return null
*/
public function checkoutOnepageControllerSuccessAction($oObserver)
{
$aOrderId = $oObserver->getOrderIds();
foreach ($aOrder as $iOrderId) {
$oOrder = Mage::getModel('sales/order')->load($iOrderId);
var_dump(
$oOrder->getCouponCode(),
$oOrder->getDiscountAmount(),
$oOrder->getGrandTotal()
);
}
}
I need to make a change of payment method to an order after it is placed. I have the order ID ($orderID), the order object ($order), a proper payment object, etc.
$service->retrievePaymentType() Returns the payment in the form of Mage_Sales_Model_Order_Payment
All of this happens in an extension of Mage_Checkout_Model_Type_Onepage
Does anybody know how I would go about doing this?
$order = Mage::getModel('sales/order')->load($orderID);
$service = Mage::getModel('sales/service_quote', $this->getQuote());
// Update Saved Order Payment Method
// $order->getPaymentsCollection()->clear();
$order->setPayment($service->retrievePaymentType());
$order->getPaymentsCollection()->save();
$order->save();
Thanks in advance!
Unfortunately, I had to do a direct SQL query, which is not Magento spec, but it gets the job done. If someone want's the code, leave me a comment, and I will dig it up.
Thanks though!
EDIT:
I managed to in fact get this working with Magento API:
// The payment type I want to change the target order to
$service = Mage::getModel('sales/service_quote', $this->getQuote());
$payment = $service->retrievePaymentType();
$paymentData = $payment->getData();
$oldPayment = $order->getAllPayments();
$oldPayment = $oldPayment[0];
foreach ($paymentData as $n => $v) {
$oldPayment->setData($n,$v);
}
It is a little bit hackish, but pretty effective.
I'm trying to write a Magento (CE 1.4) extension to export order data once an order has been paid for. I’ve set up an observer that hooks in to the sales_order_invoice_save_after event, and that is working properly - my function gets executed when an invoice is generated. But I’m having trouble getting information about the order, such as the shipping address, billing address, items ordered, order total, etc.
This is my attempt:
class Lightbulb_Blastramp_Model_Observer {
public function sendOrderToBlastramp(Varien_Event_Observer $observer) {
$invoice = $observer->getEvent()->getInvoice();
$order = $invoice->getOrder();
$shipping_address = $order->getShippingAddress();
$billing_address = $order->getBillingAddress();
$items = $invoice->getAllItems();
$total = $invoice->getGrandTotal();
return $this;
}
}
I tried doing a print_r on all those variables, and ended up getting a lot of data back. Could someone point me in the right direction of getting the shipping address of an order?
Thanks!
Many Magento objects are based on Varien_Object, which has a method called getData() to get just the usually interesting data of the object (excluding the tons of other, but mostly useless data).
With your code you could either go for all the data at once:
$shipping_address = $order->getShippingAddress();
var_dump($shipping_address->getData());
or directly for specific single properties like this:
$shipping_address = $order->getShippingAddress();
var_dump(
$shipping_address->getFirstname(),
$shipping_address->getLastname(),
$shipping_address->getCity()
);
To understand how this works, I'd recommend to make yourself more familiar with the Varien_Object and read a bit about PHPs magic methods, like __call(), __get() and __set().
Try print_r($shipping_address->toArray());