I am updating the stock status with the code below from a different system. but it shows that there is no stock when listing the product. Do I have a mistake in case of stock
update_post_meta($id,"_stock",$stok_number);
if (intval($stok_number) == 0) {
update_post_meta($id, "_stock_status", "outofstock");
} else {
update_post_meta($id, "_stock_status", "instock");
}
Better to use WC core functions. I assume the $id is a valid product ID:
$product = new WC_Product($id);
$product->set_stock_quantity($stok_number);
$stock_status = ($stock_number <= 0) ? 'outofstock' : 'instock';
$product->set_stock_status(stock_status);
$product->save();
Related
We are using the Easy Booking plugin for a client’s project and they want the ability to make the dates recurring. I.E they use the calendar to book Mon, Tues and Wed and want to have it recurring for the next 3 weeks.
We added some JS functionality, with a few form fields, that modifys the data-booking_price so that it is the price * recurring modifier. The order flow works fine while the quantity is one, but if we increase the quantity, the whole thing breaks apart. After we add the item to the cart and then go to View Cart, the price is set to the original booking price, sans the modifier.
You can view it in action here: http://bethpark.dev.ksand.com/product/meter-bags
My question is how does how does the plugin pass the total of the product along to the cart? From what I can see, it’s not updating Woo Sessions with the total that is getting generated. Is that not accurate? I realize we are modifying how the plugin inherenly works, but any sort of pointing in the right direction would be much appreciated!
-Anthony
I've updated WC()->cart->total on both the cart page and the checkout page, but it keeps getting overwritten. I've also manually set the total in WC()->sessions but that also get's overwritten (I've since commented these out since this felt extremely hacky.)
//function to detect if PHP session is started
function is_session_started()
{
if ( php_sapi_name() !== 'cli' ) {
if ( version_compare(phpversion(), '5.4.0', '>=') ) {
return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
} else {
return session_id() === '' ? FALSE : TRUE;
}
}
return FALSE;
}
add_action( 'woocommerce_before_add_to_cart_button' , 'bpa_custom_add_checkout_fields', 50, 0 );
function save_recursion(){
//if the user is getting the bags with recursive dates set, we will attempt to save them so that they can be used at a later time.
if( isset($_POST['recursive_weeks']) ){
$id = 0;
if( is_user_logged_in() ){
$id = get_current_user_id();
}
// if user is not logged in or if WP couldn't get user ID
if($id > 0){
update_user_meta($id, 'bpa_meter_bag_recursion', $_POST['recursive_weeks']);
} else {
if ( is_session_started() === FALSE ) session_start();
$_SESSION['bpa_meter_bag_recursion'] = $_POST['recursive_weeks'];
}
}
}
add_action('woocommerce_add_to_cart', 'save_recursion');
function custom_add_to_cart( $item_data, $cart_item) {
//this adds the custom recursion dates to the items data
//if this is the meter bag product
if($cart_item['product_id'] == '2476'){
//check if user is logged in, get recursion from user meta. if not try to get sessions
if( is_user_logged_in() ){
$id = get_current_user_id();
$recursion = get_user_meta($id, 'bpa_meter_bag_recursion');
$_POST['recursive_weeks'];
} else {
session_start();
$recursion = $_SESSION['bpa_meter_bag_recursion'] ;
}
// change the message to reflect that this is going to be multiple dates
$item_data[0]['name'] = "First Day of First Week";
$item_data[1]['name'] = "Last Day of First Week";
//get that first week dates in the correct format
$start_date = new DateTime($item_data[0]['value']);
$end_date = new DateTime($item_data[1]['value']);
$first_start_date = $start_date->format('Y-m-d');
$first_end_date =$end_date->format('Y-m-d');
//iterate over the recursive weeks and add these as products to the cart
$week = 1;
$quantity = $cart_item['quantity'];
for($i = 1; $i <= ($recursion[0] * 2) - 2; $i++ ){
if( ($i % 2) != 0){
$item_data[$i + 1]['name'] = "First Day of the Next Week ";
$startDate = strtotime( $first_start_date . " +" . $week ." week" );
$item_data[$i + 1]['value'] = date('F jS Y', $startDate);
} else {
$item_data[$i + 1]['name'] = "Last Day of the Next Week ";
$endDate = strtotime( $first_end_date . " +" . $week ." week");
$item_data[$i + 1]['value'] = date('F jS Y', $endDate);
$week++;
}
}
if ( is_session_started() === FALSE ) session_start();
$_SESSION['recursive_dates'] = serialize($item_data);
if( isset($_SESSION['recursive_dates']) ){
//var_dump($_SESSION['recursive_dates']);
}
return $item_data;
}
}
add_filter('woocommerce_get_item_data', 'custom_add_to_cart', 10, 2);
What I am expecting to have happen is that on the product screen, the updated product total would get added to the cart total, and viewable from the cart and checkout. This works until the quantity is increased. Not sure why this is an issue since I would presume that the total would be prod_total * quantity, but that doesn't appear to be how this works. I'm not sure if this is a woo thing or an Easy Bookings thing (I'm tending to lean towards a woo thing, but my hours of research hasn't found anything, or I'm googling the wrong stuff. )
Any help in pointing me in the right direction is mucho appreciated.
I want to insert 50k products in woocommerce using cron job. Data will come from json API. SO please guide me how can I do this job ?
$fileContents = file_get_contents(ABSPATH.'json_array.txt');
if ($fileContents === false)
{
echo 'ERROR!';
}
else
{
$data = json_decode($fileContents, true);
// count($data['DataList']; output 50000
for($i=0;$i<count($data['DataList']);$i++)
{
$Shape = $data->DataList[$i]->Shape;
$Size = $data->DataList[$i]->Size;
$Color = $data->DataList[$i]->Color;
$Clarity = $data->DataList[$i]->Clarity;
$objProduct = new WC_Product();
$objProduct->set_name($ReportNo); //Set product name.
$objProduct->set_status('publish');
$objProduct->set_featured(TRUE);
$objProduct->set_catalog_visibility('visible');
$new_product_id = $objProduct->save();
}
}
Have situation with custom price for item line in WooC.
Now find solution to change subtotal in Edit of order this way:
add_action( 'woocommerce_update_order_item', function ($_item_id, $_item, $_order_id) {
if( $arr_item_meta = wc_get_order_item_meta($_item_id) )
{
$prc = wooc_item1_price( $arr_item_meta["_a1"][0], $arr_item_meta["_a2"][0], $arr_item_meta["_a3"][0], $_item->get_product()->get_id() );
$_item -> set_total( $prc );
$_item -> set_subtotal( $prc );
$_item -> save();
}
},10,3);
This only works on edit. I.e. while updated - it set up price i make with function
wooc_item1_price with few argumens from cart (quantities of each type of product)
Problem is:
howto make same after product just added to cart.
So new subtotal+total will be available in order before any edit/updater.
Please help me!
add_action ('woocommerce_calculate_totals', function( $_cart )
{
foreach ($_cart->cart_contents as $cart_key => $cart_item)
{
$prc = function_to_make_item_custom_price(
$_cart->cart_contents[$cart_key]["_param1"],
$_cart->cart_contents[$cart_key]["_param2"],
$_cart->cart_contents[$cart_key]["_param3"],
$_cart->cart_contents[$cart_key]["product_id"]
);
$_cart->cart_contents[$cart_key]['line_subtotal'] = $prc;
$_cart->cart_contents[$cart_key]['line_total'] = $prc;
}
}, 10,1);
this is right way - make price on adding item to cart.
is need have price function function_to_make_item_custom_price to make custom price, based on parameters. In my case - this is quantites of product parts (tour adult&child&infants param1,param2,param3)
Its simplifed idea, is need also recal taxes, coupons ...
I have the following code to get a Magento 2 product collection:
<?php namespace Qxs\Related\Block;
class Related extends \Magento\Framework\View\Element\Template
{
public function __construct(
\Magento\Backend\Block\Template\Context $context,
\Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory,
\Magento\Catalog\Model\Product\Attribute\Source\Status $productStatus,
\Magento\Catalog\Model\Product\Visibility $productVisibility,
\Magento\Framework\Registry $registry,
array $data = []
)
{
$this->_productCollectionFactory = $productCollectionFactory;
$this->productStatus = $productStatus;
$this->productVisibility = $productVisibility;
$this->_registry = $registry;
parent::__construct($context, $data);
}
public function getProductCollection()
{
try {
$product = $this->_registry->registry('current_product');
$range_percentage = 35;
$price_temp = round($product->getFinalPrice() / 100 * $range_percentage);
$price_from = $product->getFinalPrice() - $price_temp;
$price_to = $product->getFinalPrice() + $price_temp;
$categories = $product->getCategoryIds();
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToSelect('*')
->addCategoriesFilter(['in' => $categories])
->addPriceDataFieldFilter('%s >= %s', ['min_price', $price_from])
->addPriceDataFieldFilter('%s <= %s', ['min_price', $price_to])
->addMinimalPrice()
->addAttributeToFilter('entity_id', ['neq' => $product->getId()])
->addAttributeToFilter('status', ['in' => $this->productStatus->getVisibleStatusIds()])
->setVisibility($this->productVisibility->getVisibleInSiteIds())
->setPageSize(5);
return $collection;
} catch (\Exception $e) {
var_dump($e->getMessage());
}
}
}
Code above is updated with a working example
It will return a result with addtofieldfilter 'price' but it does not work with final_price attribute. I need to sort based on final_price because configurable products don't have a price. The code returns: invalid attribute name.
How can I filter on price range in final_price attribute?
Thanks,
The final_price is part of the price index tables, so you can't work with it the same way as you would do with fields and attributes. You need to join in the price index to be able to filter and sort based on final_price. Luckily, Magento has added a few nifty functions for us to use on the product collection; addPriceDataFieldFilter() and addFinalPrice().
Solution
To be able to achieve the logic you describe above, you would want to change your code to something like this:
$collection = $this->_productCollectionFactory->create();
$collection->addAttributeToSelect('*')
->addCategoriesFilter(['in' => $categories])
->addPriceDataFieldFilter('%s >= %s', ['final_price', $price_from])
->addPriceDataFieldFilter('%s <= %s', ['final_price', $price_to])
->addFinalPrice()
->addAttributeToFilter('entity_id', ['neq' => $product->getId()])
->addAttributeToFilter('status', ['in' => $this->productStatus->getVisibleStatusIds()])
->setVisibility($this->productVisibility->getVisibleInSiteIds())
->setPageSize(5);
Note the order of the functions. You must always call addFinalPrice() after all of the addPriceDataFieldFilter() or else the filter won't be applied.
Bonus
If you want to sort by final_price, you can add following code after addFinalPrice():
$collection->getSelect()->order('price_index.final_price ASC');
References
https://github.com/magento/magento2/blob/2.2.9/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php#L1465
https://github.com/magento/magento2/blob/2.2.9/app/code/Magento/Catalog/Model/ResourceModel/Product/Collection.php#L2265
I am using Gravity Forms (1.8.9) and Wordpress (3.9.1)
I have a form field as a datepicker on my site, and I want to allow submissions only if the user is 21 or older to be able to submit the form.
I was originally using the following code. It only worked for a single form for a while, but then it stopped working completely: http://lanche86.com/gravity-forms-18-years-old-verification/
I would like to be able to use the same code on different forms. Help!
You can do something like this:
add_filter("gform_field_validation_1_1", "dob_validate", 10, 4);
function dob_validate($result, $value, $form, $field){
//Check if dob field matches required age
if ($result["is_valid"]){
// this the minimum age requirement we are validating
$minimum_age = 18;
// calculate age in years like a human, not a computer, based on the same birth date every year
$age = date('Y') - substr($value, 6, 4);
if (strtotime(date('Y-m-d')) - strtotime(date('Y') . '-' . substr($value, 0, 2) . '-' . substr($value, 3, 2)) < 0) {
$age--;
}
if( $age < $minimum_age ){
$result["is_valid"] = false;
$result["message"] = "Sorry, you must be at least $minimum_age years old. You're $age years old.";
}
}
//Check if dob field is empty
if(empty($value)){
$result["is_valid"] = false;
$result["message"] = "This field is required.";
}
return $result;
}
I'm using Gravity Forms 1.8.8 and latest Wordpress and works as desired. Screenshot:
You can also edit this according to form and field:
add_filter("gform_field_validation_1_1", "dob_validate", 10, 4);
Where gform_field_validation_1_1 is for form 1 and field 1. If your forms id is 8 and field number is 2, you can change it to gform_field_validation_8_2.
You can also add that same filter multiple times for multiple forms and fields without recreating the dob_validate function.
If anybody still needs to implement this, try this:
add_filter( 'gform_field_validation_1_1', function ( $result, $value, $form, $field ) {
if ( $result['is_valid'] ) {
if ( is_array( $value ) ) {
$value = array_values( $value );
}
$date_value = GFFormsModel::prepare_date( $field->dateFormat, $value );
$today = new DateTime();
$diff = $today->diff( new DateTime( $date_value ) );
$age = $diff->y;
if ( $age < 18 ) {
$result['is_valid'] = false;
$result['message'] = 'Underage';
}
}
return $result;
}, 10, 4 );
It's on Gravity Forms Documentation: https://docs.gravityforms.com/gform_field_validation/#13-date-field-age-validation