Invoice date is in GMT/UTC when programmatically creating an invoice - magento

We have a process that generates shipments every 4 hours. Only the items that are shipped should be invoiced, so invoice creation is part of this process.
This process runs in an external PHP script that loads the Magento environment and then processes the pending orders.
When the invoices are created, the create at time is off by 4 hours, so that looks like it's not using the store time. I've reviewed the Magento code and searched the web, but, I don't see any indication that you should do something to set the correct store time when creating an invoice.
At the top of the script the timezone to the store's timezone -
date_default_timezone_set('America/Boston');
The magento environment based on the order's store id -
//Start environment emulation of the specified store
$storeId = $order->getStoreId();
$initialEnvironmentInfo = $appEmulation->startEnvironmentEmulation($storeId);
Later, for order that shipment, an invoice is created -
// create an invoice for the invoiceable items
$invoice = Mage::getModel('sales/service_order', $order)->prepareInvoice($toInvoice);
if (!$invoice->getTotalQty()) {
Mage::throwException(Mage::helper('core')->__('Invoice generation failed - no items to invoice.'));
}
$invoice->setRequestedCaptureCase(Mage_Sales_Model_Order_Invoice::CAPTURE_ONLINE);
$invoice->register();
$transactionSave = Mage::getModel('core/resource_transaction')
->addObject($invoice)
->addObject($invoice->getOrder());
$transactionSave->save();
$invoiceID = $invoice->getIncrementId();
Any suggestions what should be done differently?
Thanks!

As far as I know all dates in Magento are stored as GMT.
Check this file for methods that will help you when working with dates in Magento app/code/core/Mage/Core/Model/Date.php

I read inchoo article from above and I make conclusion:
Just use formatDate() and formatTime() methods when you want to display dates and times and don't worry about anything else.

Related

Magento Product Stock status changes automatically

We are facing a issue in Magento 2.4. We are using MSI and we have 3 warehouses. All products have assigned 3 warehouse and we manage stock using MSI. A product can be available on one warehouse and can't be available on another, The issue is when we get product out of stock one day it get automatically in stock after 1 or 2 days and its random behavior not with specific products or warehouse.
Initially we thought may be its done by someone in team if they worked on same product so we have setup an alert when ever product get changed by admin we get notification on Email. But the strange thing is without any alert still status get changed.
I have used this event controller_action_catalog_product_save_entity_after to trigger an alert when ever product get changed and its working as well we have tested it.
Although we have restrict import functionality for other users, but we think product may be changed through csv or api although we have restricted but may be it can be done from any user.
Can any one please help if someone faced similar issue or any model function which always trigger when ever product stock status get changed from any action like API or from CSV or from Admin Edit or even frontend ??
I believe you can use Magento event catalog_product_save_after. Create an observer method that does the following on event catalog_product_save_after.
public function catalog_product_save_after($observer) {
$product = $observer->getProduct();
$stockData = $product->getStockData();
if ( $product && $stockData['qty'] ) {
$stock = Mage::getModel('cataloginventory/stock_item')->loadByProduct($product->getEntityId()); // Load the stock for this product
$stock->setData('is_in_stock', 1); // Set the Product to InStock
$stock->save(); // Save
}
}

Update All Product Attributes programmatically

How can I set the value of a given attribute to the same value for all products (efficiently)?
By efficient I mean in one transaction, not having to loop through the entire product collection.
In the past I've used Mage_Catalog_Model_Product_Action for bulk updates on products, and it runs pretty fast
Mage::getSingleton('catalog/product_action')
->updateAttributes($productIds, array('some_attribute' => 'some_value'), 0)
But it requires you specify which product ids you're updating, creating a huge WHERE entity_id IN(...) clause in the MySQL statement. Is there a way to do this for everything?
I had same problem before, when I added 11096 product(downloadable products) in my store then client told me to add new attributes in product so i create 1 attribute (Type is Yes/No) and set to attribute set. Now my problem is how can iIedit all product and set that attribute yes or not. If I don't set then value is null so I wrote few line code.
Please check this code may be it'll helpful to you.
$ProductId = Mage::getResourceModel('catalog/product_collection') -
addAttributeToFilter('type_id', Mage_Downloadable_Model_Product_Type::TYPE_DOWNLOADABLE) -
getAllIds(); //Now create an array of attribute_code => values
$attributeData = array("my_attribute_code" =>"my_attribute_value");
//Set the store to affect. I used admin to change all default values
$storeId = 0;
//Now Update the attribute for the given products.
Mage::getSingleton('catalog/product_action') ->updateAttributes($ProductId, $attributeData, $storeId);
It was work for me.I hope it'll work for you
Amasty "Mass Product Actions" will allow you to edit product attributes in a variety of ways. This is what we use and it's going to be a life saver once we get the Configurable Products pricing tier working properly.
http://amasty.com/mass-product-actions.html

In Magento, how can I re-populate sales_flat_order_grid after updating sales_flat_order?

we have set up a cron job that cleans off old orders for our Magento 1.4 shop. Stuff like failed payments, incomplete finance applications, stuff like that are checked and of older than x days, we change the status.
The cron job basically runs an SQL query that directly edits the sales_flat_order table in the database and changes the state/status according to our criteria.
My problem is that because we've made these changes via the back door, these changes aren't reflected in the sales_flat_order_grid table and therefore the orders grid view in the admin until you go into an order and save some part of it.
Is there some way I can force the sales_flat_order_grid to refresh/rebuild based on the contents of the sales_flat_order table?
Thanks,
James
Just had to do this recently here is a few lines that should do that job:
//update status sales_flat_order_grid
$vals = array();
$vals['status'] = $status;
$where = $write->quoteInto('entity_id =?', $order_id);
$write->update("sales_flat_order_grid", $vals ,$where);

Magento : Sales report without invoice?

I work with a client that is using purchase orders, and a custom order's process (custom statuses). So there is no invoice, and only custom statuses for the orders. The problem is, with no "admin actions" (like invoices), correct me if i'm wrong, the orders doesn't appears in the reports (even if in reports->sales->orders, I select any status (including my custom ones and any date, nothing appears), I also tried to change the timezone and refreshing lifetime statistics.
So I guess I need to modify the way magento handle these reports to include all the orders, even if it has no admin actions(no invoice or anything).
Any help on this?
Thanks!
----Edit----
Thanks for the answer, I tried changing this
if ($paymentHelper->isZeroSubTotal($storeId)
&& $this->_getOrder()->getGrandTotal() == 0
&& $zeroSubTotalPaymentAction == Mage_Payment_Model_Method_Abstract::ACTION_AUTHORIZE_CAPTURE
&& $paymentHelper->getZeroSubTotalOrderStatus($storeId) == 'pending') {
$invoice = $this->_initInvoice();
$invoice->getOrder()->setIsInProcess(true);
$invoice->save();
}
for this
$invoice = $this->_initInvoice();
$invoice->getOrder()->setIsInProcess(true);
$invoice->save();
in onepagecontroller.php so it create an invoice for each orders,
but it still doesn't appear in the sales report.
Change your process such that a complete order still generates an invoice OR rewrite all the reports. You can change your process by training your client, or you can change it by writing automated cron scripts to examine order states and programmatically generate the invoices.

Creating checkout sessions at store level

I'm trying to create different checkout sessions for the logged in customer at a store level, rather than at the site level.
We have a site with 2 stores. When a user adds a product to the cart, we want to show that product in the cart only for that store. But currently switching between stores will show up products of other stores previously added to the cart.
After some research I found that whenever a user logs in to a store, a record is created in the sales_flat_quote table for the logged in customer, which is common for all the stores in that site. So I need to create a new record in the sales_flat_quote table when the user switches stores.
I found that the loadByCustomerId() function in class Mage_Sales_Model_Mysql4_Quote is what creates the new record in the sales_flat_quote table. But all I see is a select query:
$read = $this->_getReadAdapter();
$select = $this->_getLoadSelect('customer_id', $customerId, $quote)
->where('is_active=1')
->order('updated_at desc')
->limit(1);
$data = $read->fetchRow($select);
I don't understand how the select query is creating the record in the sales_flat_quote table.
Could someone guide as to how to create a new record in this table for the logged in customer when he/she switches to an other store under the same site?
We have a site with 2 stores. When a user adds a product to the cart,
we want to show that product in the cart only for that store. But
currently switching between stores will show up products of other
stores previously added to the cart.
Which is correct.
It looks like you want to separate carts for store definitions, which both are connected to the very same website definition in Magento.
In Magento, all stores defined within the same website do always share the very same cart.
That's by-design.
To achieve cart separation you would need to change your Magento setup to have two websites and one store per website. Otherwise you'll run into endless issues separating the two stores (like the issue you're having now), I guess.
That said, I'll nevertheless try to answer your concrete question:
I don't understand how the select query is creating the record in the
sales_flat_quote table.
A SELECT query usually never ever will create a record; it's thought to read data.
Have a look at Mage_Checkout_Model_Session::loadCustomerQuote():
$customerQuote = Mage::getModel('sales/quote')
->setStoreId(Mage::app()->getStore()->getId())
->loadByCustomer(Mage::getSingleton('customer/session')->getCustomerId());
This is what leads to the call of Mage_Sales_Model_Mysql4_Quote::loadByCustomerId() you're talking about. It just loads the customers quote (if any), nothing else.
Creation/update of the record happens by calling the quotes save() method.
Magento EE 1.11.0.0 for example saves the record this way:
if ($customerQuote->getId() && $this->getQuoteId() != $customerQuote->getId()) {
if ($this->getQuoteId()) {
$customerQuote->merge($this->getQuote())
->collectTotals()
->save(); // <- either this
}
$this->setQuoteId($customerQuote->getId());
if ($this->_quote) {
$this->_quote->delete();
}
$this->_quote = $customerQuote;
} else {
$this->getQuote()->getBillingAddress();
$this->getQuote()->getShippingAddress();
$this->getQuote()->setCustomer(Mage::getSingleton('customer/session')->getCustomer())
->setTotalsCollectedFlag(false)
->collectTotals()
->save(); // <- or that does the save
}
You didn't mention the Magento version you use, so your mileage may vary, but the principle will still remain the same.

Resources