WooCommerce: Locație suplimentară a stocurilor

Publicat: 2022-12-07

Pluginul WooCommerce vă permite să gestionați stocul pentru fiecare produs, dar aveți doar un singur câmp de cantitate de stoc!

Ce se întâmplă dacă aveți două depozite și, în calitate de administrator al magazinului, trebuie să gestionați inventarul pentru fiecare locație ? În plus, ce se întâmplă dacă un articol nu este în stoc la locația 1, dar este în stoc la locația 2 și, prin urmare, clientul trebuie să îl poată achiziționa?

Această soluție uimitoare va adăuga un al doilea număr de intrare în setările produsului, va redefini cantitatea și starea stocului pe front-end prin însumarea stocului 1 + stoc 2 și, în final, va reduce stocul 1 până când ajunge la 0, după care va scădea stocul 2.

Acest comportament implicit poate fi schimbat desigur, de exemplu, este posibil să se definească de unde se reduce stocul (în funcție de distanță?) printr-un cod suplimentar. De asemenea, se poate scrie cod suplimentar pentru a-l face compatibil cu produse variabile sau tipuri de produse personalizate, precum și pentru a-l face să funcționeze cu rambursări. Oricum, bucură-te!

Iată al doilea câmp de stoc. În acest caz, cantitatea de stoc este 0 în depozitul implicit, deci din punct de vedere tehnic produsul este epuizat. Cu fragmentul de mai jos și faptul că există 1 articol în stoc în Locația 2, produsul este de fapt „în stoc” cu o cantitate de „1”. La comandă, aceasta este cantitatea care este redusă.

Fragment PHP: al doilea stoc de gestionare a locației

/**
 * @snippet       Second Stock Location @ WooCommerce Edit Product
 * @how-to        Get CustomizeWoo.com FREE
 * @author        Rodolfo Melogli
 * @compatible    WooCommerce 7
 * @donate $9     https://businessbloomer.com/bloomer-armada/
 */

add_action( 'woocommerce_product_options_stock', 'bbloomer_additional_stock_location' );

function bbloomer_additional_stock_location() {
	global $product_object;
	echo '<div class="show_if_simple show_if_variable">';
	woocommerce_wp_text_input(
		array(
			'id' => '_stock2',
			'value' => get_post_meta( $product_object->get_id(), '_stock2', true ),
			'label' => '2nd Stock Location',
			'data_type' => 'stock',
		)
	);
	echo '</div>';
}

add_action( 'save_post_product', 'bbloomer_save_additional_stock' );
  
function bbloomer_save_additional_stock( $product_id ) {
    global $typenow;
    if ( 'product' === $typenow ) {
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
		if ( isset( $_POST['_stock2'] ) ) {
			update_post_meta( $product_id, '_stock2', $_POST['_stock2'] );
		}
	}
}

add_filter( 'woocommerce_product_get_stock_quantity' , 'bbloomer_get_overall_stock_quantity', 9999, 2 );

function bbloomer_get_overall_stock_quantity( $value, $product ) {
	$value = (int) $value + (int) get_post_meta( $product->get_id(), '_stock2', true );
    return $value;
}

add_filter( 'woocommerce_product_get_stock_status' , 'bbloomer_get_overall_stock_status', 9999, 2 );

function bbloomer_get_overall_stock_status( $status, $product ) {
	if ( ! $product->managing_stock() ) return $status;
	$stock = (int) $product->get_stock_quantity() + (int) get_post_meta( $product->get_id(), '_stock2', true );
	$status = $stock && ( $stock > 0 ) ? 'instock' : 'outofstock';
    return $status;
}

add_filter( 'woocommerce_payment_complete_reduce_order_stock', 'bbloomer_maybe_reduce_second_stock', 9999, 2 );

function bbloomer_maybe_reduce_second_stock( $reduce, $order_id ) {
	$order = wc_get_order( $order_id );
	$atleastastock2change = false;
	foreach ( $order->get_items() as $item ) {	
		if ( ! $item->is_type( 'line_item' ) ) {
			continue;
		}
		$product = $item->get_product();
		$item_stock_reduced = $item->get_meta( '_reduced_stock', true );
		if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) {
			continue;
		}
		$qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
		$stock1 = (int) get_post_meta( $product->get_id(), '_stock', true );
		if ( $qty <= $stock1 ) continue;
		$atleastastock2change = true;
	}
	if ( ! $atleastastock2change ) return $reduce;	
	foreach ( $order->get_items() as $item ) {	
		if ( ! $item->is_type( 'line_item' ) ) {
			continue;
		}
		$product = $item->get_product();
		$item_stock_reduced = $item->get_meta( '_reduced_stock', true );
		if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) {
			continue;
		}	
		$item_name = $product->get_formatted_name();
		$qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $order, $item );
		$stock1 = (int) get_post_meta( $product->get_id(), '_stock', true );
		$stock2 = (int) get_post_meta( $product->get_id(), '_stock2', true );
		if ( $qty <= $stock1 ) {
			wc_update_product_stock( $product, $qty, 'decrease' );
			$order->add_order_note( sprintf( 'Reduced stock for item "%s"; Stock 1: "%s" to "%s".', $item_name, $stock1, $stock1 - $qty ) );
		} else {		
			$newstock2 = $stock2 - ( $qty - $stock1 );
			wc_update_product_stock( $product, $stock1, 'decrease' );
			update_post_meta( $product->get_id(), '_stock2', $newstock2 );
			$item->add_meta_data( '_reduced_stock', $qty, true );
			$item->save();				
			$order->add_order_note( sprintf( 'Reduced stock for item "%s"; Stock 1: "%s" to "0" and Stock 2: "%s" to "%s".', $item_name, $stock1, $stock2, $newstock2 ) );
		}
	}
	$order->get_data_store()->set_stock_reduced( $order_id, true );
	return false;
}

În engleză simplă:

  • bbloomer_additional_stock_location arată al doilea câmp pentru cantitatea de stoc
  • bbloomer_save_additional_stock salvează stocul personalizat
  • bbloomer_get_overall_stock_quantity setează stocul de produse la stoc 1 + stoc 2
  • bbloomer_get_overall_stock_status setează starea stocului produsului pe baza stocului 1 + stoc 2
  • bbloomer_maybe_reduce_second_stock scade stocul din stocul 1 și apoi din stocul 2 în cazul în care cantitatea comandată este mai mare decât stocul 1, altfel permite WooCommerce să facă scăderea implicită a stocului