I'm having trouble with getting customer address Id as it returns a null value.
This is what I have tried:
$checkout = $this->_sessionCheckout->getQuote();
if ($checkout) {
$shippingAddress = $checkout->getShippingAddress();
if ($shippingAddress) {
$addressId = $shippingAddress->getCustomerAddressId();
$this->_logger->log(100, print_r('address Id: ' . $addressId , true)); //Returns null
/** #var \Magento\Customer\Api\Data\AddressInterface $address */
$address = $this->_addressRepository->getById($addressId);
$address->setCity($city_name);
$this->_addressRepository->save($address);
}
I just need to get customer address Id in order to update the city. I don't know why it returns a null value.
Edited Details:
The below image shows the saved shipping addresses:
shipping-addresses
What I want to know is How to know the customer address id of each of those shipping addresses. So I can modify any details I want.
When you place an order as a guest user, you have to add shipping address on checkout page at that time there will be not a customer reference object, so you get value of customer address Id to null.
When you place an order as a registered customer, you should have default shipping address, then only you can get the value of customer address Id.
This happen because customer_address_id is a reference to customer_address table and customer_address table reference to customer_entity table.
You can get the order as follows
Whereever your want to invoke this information add following in the Constructor if not already being used.
protected $checkoutSession;
public function __construct(
\Magento\Checkout\Model\Session $checkoutSession,
\Psr\Log\LoggerInterface $logger
)
{
$this->checkoutSession = $checkoutSession;
$this->logger = $logger;
}
$order = $session->getLastRealOrder();
$orderdata = $order->getData();
$shipping_address_id = $orderdata['shipping_address_ID'];
This address is the final shipping address selected during payment
stage of the checkout process.
Related
How do I get the collection from shipping_tablerate table rate shipping module from Magento 2.3?
I need to check customer postal code eligibility to table rate shipping module
You need to create a plugin to override this method collectCarrierRates located in /vendor/magento/module-shipping/Model/Shipping.php to check if postcode customer input that meet your requirements and then do your logic. Not sure what do you really want here, so I apply a general solution to you and this can apply to other cases as well. You can also switch to before and around plugin depends on your need.
namespace Vendor\ModuleName\Plugin\Magento\Shipping\Model;
class Shipping
{
public function afterCollectRates(
\Magento\Shipping\Model\Shipping $subject,
$result,
$request
) {
$allproducts = $request->getAllItems();
$postcode = $request->getDestPostcode();
if($postcode == 'your value here') {
'your logic here'
}
return $result;
}
}
How can I get the customer and cart during collectRates() function of my custom shipping method.
public function __construct(
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Quote\Model\Quote\Address\RateResult\ErrorFactory $rateErrorFactory,
\Psr\Log\LoggerInterface $logger,
\Magento\Shipping\Model\Rate\ResultFactory $rateResultFactory,
\Magento\Quote\Model\Quote\Address\RateResult\MethodFactory $rateMethodFactory,
\Magento\Checkout\Model\Cart $cart,
\Magento\Customer\Model\Session $customerSession,
array $data = []
) {
$this->_cart = $cart;
$this->_rateResultFactory = $rateResultFactory;
$this->_rateMethodFactory = $rateMethodFactory;
$this->_customerSession = $customerSession;
parent::__construct($scopeConfig, $rateErrorFactory, $logger, $data);
}
public function collectRates(RateRequest $request)
{
if (!$this->getConfigFlag('active')) {
return false;
}
if(!$this->_customerSession->isLoggedIn()) {
return false;
}
$customer = $this->_customerSession->getCustomer();
$qty = $this->_cart->getItemsQty();
...
Using customer session and checking if isLoggedIn() only works for frontend but returns false when placing order in the admin.
How can I get customer properly and calculate my price per item for both frontend and admin order placement?
If you can detect when your code runs in Admin, you can use
\Magento\Backend\Model\Session\Quote
as your [admin_session] and use [admin_session]->getCustomerId(), along with the customer repository (inject interfaces in constructor and let DI pass the correct objects) to fetch the customer object.
I would suggest to check the contents of the \Magento\Backend\Model\Session\Quote object, as it might contain a pre-loaded customer object already, in which case you can avoid loading it.
You could use \Magento\Framework\App\State::getAreaCode() to check if within admin
Magento 2: Get Product Stock Quantity and Other Stock Information
How to get the product stock quantity and information in magento 2
If we look at the StockItemRepository class the get method wants parameter $stockItemId, not $productId. Reference:
https://github.com/magento/magento2/blob/develop/app/code/Magento/CatalogInventory/Model/Stock/StockItemRepository.php#L202
I've seen many sites where stock item id IS NOT the same as product id and we should not assume it's the same ID.
To get this working you could use \Magento\CatalogInventory\Model\Stock\Item class instead and load the model by product_id field instead. I am also aware of the website_id and stock_id fields, but as far as I know it's not used (yet) and also existed in M1.
It should look something like this (code not tested):
<?php
namespace Vendor\Module\Model;
use \Magento\CatalogInventory\Model\Stock\Item;
class Mymodel
{
/**
* #var Item
*/
protected $stockItem;
/**
* Mymodel constructor.
*
* #param Item $stockItem
*/
public function __construct(Item $stockItem)
{
$this->stockItem = $stockItem;
}
/**
* Description
*
* #param $productModel
*/
public function getStockQtyByProductId($productModel)
{
try {
$stockItem = $this->stockItem->load($productModel->getId(), 'product_id');
return $stockItem->getQty();
} catch (\Exception $e) {
echo 'Something went wrong and was not handled: ' . $e->getMessage();
exit;
}
}
}
if you have product object then just use following:
echo $_product->getExtensionAttributes()->getStockItem()->getQty();
conplete object can be find as follow:
var_dump($_product->getExtensionAttributes()->getStockItem()->getData());
Actually this operation should be performed using \Magento\CatalogInventory\Api\StockRegistryInterface and here we can obtain \Magento\CatalogInventory\Api\Data\StockItemInterface, by product id or sku and we can use bunch of usefull methods to get stock information - linked product. For general stock information I recommend explore other service contracts declared in Magento\CatalogInventory\Api
Example of usage:
<?php
namespace Test\Test\Model;
class Test
{
protected $_stockRegistry;
public function __construct(\Magento\CatalogInventory\Api\StockRegistryInterface $stockRegistry)
{
$this->_stockRegistry = $stockRegistry;
}
public function getStockItem($productId)
{
return $this->_stockRegistry->getStockItem($productId);
}
}
this code help you to get product quantity
<?php
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$StockState = $objectManager->get('\Magento\CatalogInventory\Api\StockStateInterface');
echo $StockState->getStockQty($productId);
?>
If you have the product object and do not want to use the other classes, You can try in the following way.
// For phtml file
$prodObj = $_product->load($_product->getId()); // $_product object in list.phtml
$stockItem = $prodObj->getExtensionAttributes()->getStockItem();
$stockQty = $stockItem->getQty(); // $stockItemData = $stockItem->getData();
// For php class file
$stockItem = $prodObj->getExtensionAttributes()->getStockItem();
$stockQty = $stockItem->getQty(); // $stockItemData = $stockItem->getData();
Credits:
https://github.com/magento/magento2/issues/7057#issuecomment-256052729
Actually \Magento\CatalogInventory\Api\Data\StockStatusInterface
should answer to all your questions.
Long story short:
Magento has StockItem entity which represents amount (Qty) of specific product (productId) on a concrete stock (stockId).
StockItemInterface should be used when you would like to "write" data into the data storage (like update amount of products to sync up Magento with your ERP system or to make deduction of stock during the checkout process).
StockStatusInterface is opposite to it. It should be used to "read" data for representation (on front-end). Consider StockStatus as an index which contains aggregated stock data for each specific product.
So, if you would like to get product stock status (in stock, out of stock) by product_id.
You need using StockStatusRepositoryInterface::getList(StockStatusCriteriaInterface $searchCriteria);
get StockStatus entity for specified product
/** #var \Magento\CatalogInventory\Api\StockStatusCriteriaInterfaceFactory $stockStatusCriteriaFactory **/
$criteria = $stockStatusCriteriaFactory->create();
$criteria->setProductsFilter($productId);
/** #var \Magento\CatalogInventory\Api\Data\StockStatusRepositoryInterface $stockStatusRepository **/
$result = $stockStatusRepository->getList($criteria);
$stockStatus = current($result->getItems());
$stockStatus->getProductId(); // product id
$stockStatus->getQty(); // quantity of specified product
$stockStatus->getStockStatus(); // Could be
// Magento\CatalogInventory\Model\Stock\Status::STATUS_OUT_OF_STOCK = 0;
// or
// Magento\CatalogInventory\Model\Stock\Status::STATUS_IN_STOCK = 1;
I want to implement php classes that should model the following :
(Symfony,DoctrineMongoDBBundle)
Notification Collection { from { id , fname } , to , sentDate }
Member Collection { id , fname , lname , email , phone , regDate , ... }
And i want tell to ODM : "from field is an object that holds only 2 values ,id of the sender and his fname"
What annotation i must use? Should i define another class like from.php ? Or i can create two classes as the following:
/*
*#Document
*/
class Notification {
/*
*#Id
*/
protected $id;
/*
*#EmbedOne(targetDocument="Member")
*/
protected $from;
/*
*#ReferenceOne(targetDocument="Member")
*/
protected $to;
/*
*#Date
*/
protected $sentDate;
}
/*
*#Document
*/
class Member {
/*
*#Id
*/
protected $id;
/*
*#String
*/
protected $fname;
/*
*#String
*/
protected $lname;
/*
*#String
*/
protected $email;
.
.
.
}
If it's correct,in my controller how can i control "from" field to hold only id and fname from a Member object?
suppose this:
$senderUser;
$newNotification = new Notification();
$newNotification->setFrom($senderUser);
Then $newNotification->from set to a Member object that hold all info about a Member.But i want only id and fname of the sender to persist! (because needs of my project)
Excuse my English grammatical errors.
Thanks for any help...
If you insist on nesting the notification's originating user ID and first name in a from field, then you will need an Embed One relationship to a From document, which in turn has the following fields:
id: this should be a Reference One relationship to a Member document. I would suggest using the simple option for the reference, so that you only store the Member's ID value, rather than a DBRef object.
fname: this should be a string field. ODM has no facility for keeping it up-to-date with the referenced Member document, so you will need to ensure that on your own.
Personally, the Notification document seems small enough that I would simply create fromMember and fromMemberFirstName fields directly on Notification. Then, you could add some logic in the setFromMember() method that also sets the fromMemberFirstName field from the passed Member argument.
If you want to take things a step further, you could explore using events to monitor Member objects for changed fname fields and issue queries to update Notification documents, but that's a separate conversation.
I use the include Method in my asp.net mvc 2 project with EF 4.0
Here is my database structure.
Contact
ContactID
ContactName
AddressID (FK)
Address
AddressID
CodePostal
Street
A contact can contain an address or not.
In some case, I dont want any address. In that case, the AddressID in the contact table will be null.
I try to do this
_db.LocationContacts.Include("Contact.Address.City.Province.Country")
Thats give me an error if there is no address associate to the contact.
Is there a way to resolve that situation.
Thanks a lot.
This is the Error Message : System.NullReferenceException: Object reference not set to an instance of an object.
This line ...
var location = _db.LocationContacts
.Include("Contact.Address.City.Province.Country").First();
... does not throw a NullReferenceException. It happens later when you access location.Address.City or some other property or method of Address and Address is null (which is expected for some locations because it is allowed to have NULL values).
You just need to check if location.Address is null or not:
if (location.Address != null)
{
var city = location.Address.City; // OK
}
else
{
// var city = location.Address.City; // Not OK
}
Because you are accssing the City which is under Address which is null !
Use it like this
var contacts=_db.LocationContacts.Include("Contact.Address").ToList();
That gives you contacts with Address.