Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add support for syncing the "Mark as Sold Out" field value during inventory sync. #277

Draft
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions includes/Handlers/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,13 +462,15 @@ public static function update_stock_from_square( \WC_Product $product, $save = t
}
}

$is_inventory_tracking = isset( $inventory_tracking[ $square_id ] ) ? $inventory_tracking[ $square_id ] : true;
$inventory_tracking_data = $inventory_tracking[ $square_id ] ?? array();
$is_inventory_tracking = $inventory_tracking_data['track_inventory'] ?? true;
$sold_out = $inventory_tracking_data['sold_out'] ?? false;

if ( $is_inventory_tracking ) {
$product->set_manage_stock( true );
$product->set_stock_quantity( $stock );
} else {
$product->set_stock_status( 'instock' );
$product->set_stock_status( $sold_out ? 'outofstock' : 'instock' );
$product->set_manage_stock( false );
}

Expand Down Expand Up @@ -512,9 +514,11 @@ public static function update_products_stock_from_square( $product_ids ) {
$inventory_tracking = Helper::get_catalog_inventory_tracking( $response->get_data()->getObjects() );

foreach ( $response->get_data()->getObjects() as $catalog_object ) {
$square_id = $catalog_object->getId();
$stock = $inventory_hash[ $square_id ] ?? 0;
$is_inventory_tracking = isset( $inventory_tracking[ $square_id ] ) ? $inventory_tracking[ $square_id ] : true;
$square_id = $catalog_object->getId();
$stock = $inventory_hash[ $square_id ] ?? 0;
$inventory_tracking_data = $inventory_tracking[ $square_id ] ?? array();
$is_inventory_tracking = $inventory_tracking_data['track_inventory'] ?? true;
$sold_out = $inventory_tracking_data['sold_out'] ?? false;

$product_id = $products_map[ $square_id ]['product_id'];
$product = wc_get_product( $product_id );
Expand All @@ -527,7 +531,7 @@ public static function update_products_stock_from_square( $product_ids ) {
$product->set_manage_stock( true );
$product->set_stock_quantity( $stock );
} else {
$product->set_stock_status( 'instock' );
$product->set_stock_status( $sold_out ? 'outofstock' : 'instock' );
$product->set_manage_stock( false );
}

Expand Down
20 changes: 18 additions & 2 deletions includes/Handlers/Product/Woo_SOR.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,14 +229,30 @@ public static function update_catalog_variation( CatalogObject $catalog_object,
}

if ( wc_square()->get_settings_handler()->is_inventory_sync_enabled() ) {
$track_inventory = $variation_data->getTrackInventory();
$location_overrides = $variation_data->getLocationOverrides();

/*
* Only update track_inventory if it's not set.
* This will only update inventory tracking on new variations.
* inventory tracking will remain the same for existing variations.
*/
$track_inventory = $variation_data->getTrackInventory();
if ( is_null( $track_inventory ) ) {
if ( is_null( $track_inventory ) && is_null( $location_overrides ) ) {
$variation_data->setTrackInventory( $product->get_manage_stock() );

// If the product is not managing stock and is out of stock, set it as sold out.
if ( ! $product->get_manage_stock() && 'outofstock' === $product->get_stock_status() ) {
$configured_location = wc_square()->get_settings_handler()->get_location_id();
$location_override = new \Square\Models\ItemVariationLocationOverrides();
$location_override->setLocationId( $configured_location );
// We need to set track_inventory to true to be able to set sold_out to true, without it will be ignored.
$location_override->setTrackInventory( true );
$location_override->setSoldOut( true );
$location_overrides = array( $location_override );

// Set the location overrides.
$variation_data->setLocationOverrides( $location_overrides );
}
}
}

Expand Down
20 changes: 16 additions & 4 deletions includes/Sync/Helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ public static function get_catalog_inventory_tracking( $catalog_objects ) {
$location_overrides = $variation_data->getLocationOverrides();
$configured_location = wc_square()->get_settings_handler()->get_location_id();

$default_data = array(
'track_inventory' => $variation_data->getTrackInventory(),
'sold_out' => false,
);

if ( ! empty( $location_overrides ) ) {
$location_ids = array_map(
function ( $location_override ) {
Expand All @@ -113,23 +118,30 @@ function ( $location_override ) {
);

if ( ! in_array( $configured_location, $location_ids, true ) ) {
$catalog_objects_tracking[ $catalog_object->getId() ] = $variation_data->getTrackInventory();
$catalog_objects_tracking[ $catalog_object->getId() ] = $default_data;
continue;
}

foreach ( $location_overrides as $location_override ) {
$location_id = $location_override->getLocationId();

if ( $configured_location === $location_id ) {
$sold_out = $location_override->getSoldOut() ?? false;
if ( ! is_null( $location_override->getTrackInventory() ) ) {
$catalog_objects_tracking[ $catalog_object->getId() ] = $location_override->getTrackInventory();
$catalog_objects_tracking[ $catalog_object->getId() ] = array(
'track_inventory' => $location_override->getTrackInventory(),
'sold_out' => $sold_out,
);
} else {
$catalog_objects_tracking[ $catalog_object->getId() ] = $variation_data->getTrackInventory();
$catalog_objects_tracking[ $catalog_object->getId() ] = array(
'track_inventory' => $variation_data->getTrackInventory(),
'sold_out' => $sold_out,
);
}
}
}
} else {
$catalog_objects_tracking[ $catalog_object->getId() ] = $variation_data->getTrackInventory();
$catalog_objects_tracking[ $catalog_object->getId() ] = $default_data;
}
}

Expand Down
29 changes: 17 additions & 12 deletions includes/Sync/Interval_Polling.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,17 @@ protected function update_inventory_tracking() {
$catalog_objects_tracking_stats = Helper::get_catalog_inventory_tracking( $objects );
$catalog_objects_to_update = array();

foreach ( $catalog_objects_tracking_stats as $catalog_object_id => $is_tracking_inventory ) {
$product = Product::get_product_by_square_variation_id( $catalog_object_id );
foreach ( $catalog_objects_tracking_stats as $catalog_object_id => $inventory_data ) {
$is_tracking_inventory = $inventory_data['track_inventory'] ?? true;
$sold_out = $inventory_data['sold_out'] ?? false;
$product = Product::get_product_by_square_variation_id( $catalog_object_id );
if ( $product instanceof \WC_Product ) {
$manage_stock = $product->get_manage_stock();
// If Inventory tracking is the same as the product's manage stock setting, skip.
if ( (bool) $is_tracking_inventory === (bool) $manage_stock ) {
$stock_status = $product->get_stock_status();
$out_of_stock = 'outofstock' === $stock_status;

// If Inventory tracking is the same as the product's manage stock setting and sold_old value same, skip.
if ( (bool) $is_tracking_inventory === (bool) $manage_stock && (bool) $sold_out === (bool) $out_of_stock ) {
continue;
}
$catalog_objects_to_update[] = $catalog_object_id;
Expand All @@ -297,9 +302,9 @@ protected function update_inventory_tracking() {
foreach ( $catalog_objects_to_update as $catalog_object_id ) {
$product = Product::get_product_by_square_variation_id( $catalog_object_id );
if ( $product instanceof \WC_Product ) {
$is_tracking_inventory = isset( $catalog_objects_tracking_stats[ $catalog_object_id ] ) ?
$catalog_objects_tracking_stats[ $catalog_object_id ] :
true;
$inventory_data = $catalog_objects_tracking_stats[ $catalog_object_id ] ?? array();
$is_tracking_inventory = $inventory_data['track_inventory'] ?? true;
$sold_out = $inventory_data['sold_out'] ?? false;

/* If catalog object is tracked and has a quantity > 0 set in Square. */
if ( $is_tracking_inventory && isset( $inventory_hash[ $catalog_object_id ] ) ) {
Expand All @@ -313,7 +318,7 @@ protected function update_inventory_tracking() {

/* If the catalog object is not tracked in Square at all. */
} else {
$product->set_stock_status( 'instock' );
$product->set_stock_status( $sold_out ? 'outofstock' : 'instock' );
$product->set_manage_stock( false );
}

Expand Down Expand Up @@ -401,15 +406,15 @@ protected function update_inventory_counts() {

// Square can return multiple "types" of counts, WooCommerce only distinguishes whether a product is in stock or not
if ( $product instanceof \WC_Product ) {
$is_tracking_inventory = isset( $catalog_objects_tracking_stats[ $catalog_object_id ] ) ?
$catalog_objects_tracking_stats[ $catalog_object_id ] :
true;
$inventory_data = $catalog_objects_tracking_stats[ $catalog_object_id ] ?? array();
$is_tracking_inventory = $inventory_data['track_inventory'] ?? true;
$sold_out = $inventory_data['sold_out'] ?? false;

if ( $is_tracking_inventory ) {
$product->set_manage_stock( true );
$product->set_stock_quantity( $stats['quantity'] );
} else {
$product->set_stock_status( 'instock' );
$product->set_stock_status( $sold_out ? 'outofstock' : 'instock' );
$product->set_manage_stock( false );
}

Expand Down
6 changes: 4 additions & 2 deletions includes/Sync/Manual_Synchronization.php
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,9 @@ protected function pull_inventory() {

$catalog_objects_tracking_stats = Helper::get_catalog_objects_tracking_stats( $catalog_object_ids );

foreach ( $catalog_objects_tracking_stats as $catalog_object_id => $is_tracking_inventory ) {
foreach ( $catalog_objects_tracking_stats as $catalog_object_id => $inventory_data ) {
$is_tracking_inventory = $inventory_data['track_inventory'] ?? true;
$sold_out = $inventory_data['sold_out'] ?? false;

if ( in_array( $catalog_object_id, $in_progress['processed_variation_ids'], false ) ) { // phpcs:disable WordPress.PHP.StrictInArray.FoundNonStrictFalse
continue;
Expand All @@ -1545,7 +1547,7 @@ protected function pull_inventory() {

/* If the catalog object is not tracked in Square at all. */
} else {
$product->set_stock_status( 'instock' );
$product->set_stock_status( $sold_out ? 'outofstock' : 'instock' );
$product->set_manage_stock( false );
}

Expand Down
8 changes: 4 additions & 4 deletions includes/Sync/Product_Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,9 @@ static function( \Square\Models\CatalogObject $catalog_object ) {
$product = Product::get_product_by_square_variation_id( $catalog_object->getId() );

if ( $product && $product instanceof \WC_Product ) {
$is_tracking_inventory = isset( $catalog_objects_hash[ $catalog_object->getId() ] ) ?
$catalog_objects_hash[ $catalog_object->getId() ] :
false;
$inventory_data = $catalog_objects_hash[ $catalog_object->getId() ] ?? array();
$is_tracking_inventory = $inventory_data['track_inventory'] ?? true;
$sold_out = $inventory_data['sold_out'] ?? false;

/* If catalog object is tracked and has a quantity > 0 set in Square. */
if ( $is_tracking_inventory && isset( $inventory_hash[ $catalog_object->getId() ] ) ) {
Expand All @@ -301,7 +301,7 @@ static function( \Square\Models\CatalogObject $catalog_object ) {

/* If the catalog object is not tracked in Square at all. */
} else {
$product->set_stock_status( 'instock' );
$product->set_stock_status( $sold_out ? 'outofstock' : 'instock' );
$product->set_manage_stock( false );
}

Expand Down
26 changes: 24 additions & 2 deletions src/js/admin/wc-square-admin-products.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ jQuery( document ).ready( ( $ ) => {
}
} else {
$stockQty.prop( 'readonly', false );
$stockStatus.prop( 'readonly', false );
$stockStatus.off('mousedown keydown change');
$stockStatus.css( {
opacity: 1,
} );
}
} else {
$manageStockInput.on( 'click', () => {
Expand All @@ -129,7 +132,12 @@ jQuery( document ).ready( ( $ ) => {
$( '.backorder_field' ).hide();
} else {
$stockQty.prop( 'readonly', true );
$stockStatus.prop( 'readonly', true );
$stockStatus.on( 'mousedown keydown change', () => {
return false;
} );
$stockStatus.css( {
opacity: 0.5,
} );
}
}
} ).trigger( 'change' );
Expand Down Expand Up @@ -328,6 +336,9 @@ jQuery( document ).ready( ( $ ) => {
const $stockFields = $( '.stock_fields' );
const $stockInput = $stockFields.find( '#_stock' );
const $stockStatus = $( '.stock_status_field' );
const $stockStatusInput = $stockStatus.find(
'input[name="_stock_status"]'
);
const $manageField = $( '._manage_stock_field' );
const $manageInput = $manageField.find( '#_manage_stock' );
const $manageDesc = $manageField.find( '.description' );
Expand Down Expand Up @@ -372,6 +383,10 @@ jQuery( document ).ready( ( $ ) => {
});
$manageInput.css({ opacity: '0.5' });

// disable stock status radios.
$stockStatusInput.css({ opacity: 0.5 });
$stockStatusInput.on('mousedown keydown click', () => { return false; });

$stockInput.prop( 'readonly', true );

// WooCommerce SoR - note: for variable products, the stock can be fetched for individual variations.
Expand Down Expand Up @@ -447,6 +462,8 @@ jQuery( document ).ready( ( $ ) => {
$manageInput.off( 'click' );
$manageInput.css( { opacity: 1 } );
$manageInput.prop( 'checked', manageStockOriginal );
$stockStatusInput.css({ opacity: 1 });
$stockStatusInput.off('mousedown keydown click');

if ( ! variableProduct ) {
if ( manageStockOriginal ) {
Expand All @@ -467,6 +484,7 @@ jQuery( document ).ready( ( $ ) => {
const $variationManageField = $variationManageInput.parent();
const $variationStockInput = $( e ).find( '.wc_input_stock' );
const $variationStockField = $variationStockInput.parent();
const $variationStockStatusField = $( e ).find( '.variable_stock_status select' );

// Square manages variations stock
if ( useSquare ) {
Expand All @@ -476,6 +494,8 @@ jQuery( document ).ready( ( $ ) => {
return false;
});
$variationManageInput.css( { opacity: '0.5' } );
$variationStockStatusField.css( { opacity: 0.5 } );
$variationStockStatusField.on('mousedown keydown change', () => { return false; });

// add a note that the variation stock is managed by square, but check if it wasn't added already to avoid duplicates.
if ( 0 === $variationManageField.find( '.description' ).length ) {
Expand Down Expand Up @@ -564,6 +584,8 @@ jQuery( document ).ready( ( $ ) => {
$variationManageInput.off( 'click' );
$variationManageInput.css( { opacity: 1 } );
$variationManageInput.next( '.description' ).remove();
$variationStockStatusField.css( { opacity: 1 } );
$variationStockStatusField.off( 'mousedown keydown change' );
}
} );
// initial page load handling.
Expand Down
Loading