Skip to content

Commit

Permalink
Adding support for product variants (#160)
Browse files Browse the repository at this point in the history
- The plugin now supports the DK variant module (I just found out that it is a thing last week)
- Variations are synced between DK and WooCommerce (WooCommerce Variants are created and deleted on sync)
- Variants can also be generated from products in the UI — those are not indicated as variants in DK
  • Loading branch information
aldavigdis authored Jul 14, 2024
1 parent af0f0fa commit a9a29aa
Show file tree
Hide file tree
Showing 13 changed files with 1,397 additions and 41 deletions.
48 changes: 48 additions & 0 deletions js/products.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
class NineteenEightyWooProducts {
static actionSelect() {
return document.getElementById( 'bulk-action-selector-top' );
}

static addProductIdInputToActions() {
let actionsContainer = document.querySelector( '#posts-filter .bulkactions' );
let actionButton = document.getElementById( 'doaction' );
let productIdInput = document.createElement( 'input' );
let spacerTextNode = document.createTextNode( ' ' );

productIdInput.setAttribute( 'type', 'text' );
productIdInput.setAttribute( 'name', 'action_post_id' );
productIdInput.setAttribute( 'id', 'action_post_id_input' );
productIdInput.setAttribute( 'placeholder', 'Parent ID' );

actionsContainer.insertBefore( productIdInput, actionButton );
actionsContainer.insertBefore( spacerTextNode, actionButton );
}

static removeProductInputFromActions() {
let element = document.getElementById( 'action_post_id_input' );

if ( element !== null ) {
element.remove();
}
}

static selectMenuEvent( e ) {
if ( e.target.value == 'convert_to_variant' ) {
NineteenEightyWooProducts.addProductIdInputToActions();
} else {
NineteenEightyWooProducts.removeProductInputFromActions();
}
}
}

window.addEventListener(
'DOMContentLoaded',
() => {
NineteenEightyWooProducts.actionSelect().addEventListener(
'change',
( e ) => {
NineteenEightyWooProducts.selectMenuEvent( e );
}
);
}
);
6 changes: 6 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

<!-- Use WordPress as the basis of our ruleset -->
<rule ref="WordPress">
<!--
Absolutely ignoring that slow queries may occur when looking things up
by meta.
-->
<exclude name="WordPress.DB.SlowDBQuery" />

<!--
We are not limited by WordPress' naming constraints and are using PSR-4
autoloading, so we'll use that file naming convention.
Expand Down
34 changes: 26 additions & 8 deletions src/Export/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use NineteenEightyFour\NineteenEightyWoo\Hooks\KennitalaField;
use NineteenEightyFour\NineteenEightyWoo\Helpers\Order as OrderHelper;
use NineteenEightyFour\NineteenEightyWoo\Export\Customer as ExportCustomer;
use NineteenEightyFour\NineteenEightyWoo\Import\ProductVariations;
use WC_Customer;
use WC_Order;
use WC_Product_Variation;
Expand Down Expand Up @@ -156,7 +157,8 @@ public static function to_dk_order_body( WC_Order $wc_order ): array {

foreach ( $wc_order->get_items() as $key => $item ) {
$order_item_product = new WC_Order_Item_Product( $item->get_id() );
$product = $order_item_product->get_product();
$product_id = $order_item_product->get_product_id();
$product = wc_get_product( $product_id );
$sku = $product->get_sku();

$order_line_item = array(
Expand All @@ -170,15 +172,31 @@ public static function to_dk_order_body( WC_Order $wc_order ): array {
'IncludingVAT' => wc_prices_include_tax(),
);

if ( $product instanceof WC_Product_Variation ) {
$order_line_item['Variation'] = array();
$origin = $product->get_meta( '1984_dk_woo_origin', true, 'edit' );
$variant_code = $product->get_meta( '1984_dk_woo_variant_code', true, 'edit' );
$variation = wc_get_product( $order_item_product->get_variation_id() );

$variation_attributes = $product->get_variation_attributes(
false
);
foreach ( $variation_attributes as $key => $v ) {
$order_line_item['Variation'][] = array( "$key" => "$v" );
if (
'product_variation' === $origin &&
false !== $variation
) {
$attributes = ProductVariations::attributes_to_woocommerce_variation_attributes( $variant_code );

$variation_attributes = array_keys( $attributes );

$variation_line = array();

if ( key_exists( 0, $variation_attributes ) ) {
$variation_line['Code'] = $variation->get_attribute( $variation_attributes[0] );
}

if ( key_exists( 1, $variation_attributes ) ) {
$variation_line['Code2'] = $variation->get_attribute( $variation_attributes[1] );
}

$variation_line['Quantity'] = $item->get_quantity();

$order_line_item['Variations'] = array( (object) $variation_line );
}

$order_props['Lines'][] = $order_line_item;
Expand Down
64 changes: 43 additions & 21 deletions src/Export/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ public static function to_dk_product_body(
public static function to_new_product_body(
WC_Product $wc_product
): stdClass {
$parent = wc_get_product( $wc_product->get_parent_id() );
$product_props = array(
'ItemCode' => $wc_product->get_sku(),
'Description' => $wc_product->get_title(),
Expand All @@ -380,6 +381,30 @@ public static function to_new_product_body(
'Inactive' => false,
);

if ( $wc_product instanceof WC_Product_Variation ) {
if ( 'product' === $wc_product->get_meta( '1984_dk_woo_origin' ) ) {
$product_props['Description'] = $wc_product->get_meta(
'1984_dk_woo_original_name',
true
);

if ( $parent ) {
$description = implode(
'; ',
array(
$wc_product->get_title(),
$wc_product->get_attribute_summary(),
)
);

$product_props['Description2'] = $description;
}
} else {
$product_props['Description'] = $wc_product->get_title();
$product_props['Description2'] = $wc_product->get_attribute_summary();
}
}

if ( true === wc_prices_include_tax() ) {
$product_props['UnitPrice1WithTax'] = $wc_product->get_regular_price();
} else {
Expand All @@ -392,10 +417,6 @@ public static function to_new_product_body(
$product_props['ShowItemInWebShop'] = false;
}

if ( $wc_product instanceof WC_Product_Variation ) {
$product_props['Description2'] = $wc_product->get_attribute_summary();
}

$ledger_codes = ProductHelper::get_ledger_codes( $wc_product );

if ( false !== $ledger_codes ) {
Expand Down Expand Up @@ -423,27 +444,28 @@ public static function to_updated_product_body(
$product_props = array();

if ( ProductHelper::name_sync_enabled( $wc_product ) ) {
$name_props = array(
'Description' => $wc_product->get_title(),
);

if ( $wc_product instanceof WC_Product_Variation ) {
$name_props['Description2'] = $wc_product->get_attribute_summary();
$name = $wc_product->get_meta(
'1984_dk_woo_original_name',
true
);

$description = implode(
'; ',
array(
$wc_product->get_title(),
$wc_product->get_attribute_summary(),
)
);

$product_props['Description'] = $name;
$product_props['Description2'] = $description;
} else {
$product_props['Description'] = $wc_product->get_name();
}

$product_props = array_merge( $product_props, $name_props );
}

$product_dk_currency = $wc_product->get_meta(
'1984_woo_dk_dk_currency',
true,
'edit'
);

if (
( get_woocommerce_currency() === $product_dk_currency ) &&
ProductHelper::price_sync_enabled( $wc_product )
) {
if ( ProductHelper::price_sync_enabled( $wc_product ) ) {
$price_props = array(
'CurrencyCode' => get_woocommerce_currency(),
'TaxPercent' => ProductHelper::tax_rate( $wc_product ),
Expand Down
105 changes: 105 additions & 0 deletions src/Helpers/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
use NineteenEightyFour\NineteenEightyWoo\Config;
use NineteenEightyFour\NineteenEightyWoo\Brick\Math\BigDecimal;
use NineteenEightyFour\NineteenEightyWoo\Brick\Math\RoundingMode;
use NineteenEightyFour\NineteenEightyWoo\Hooks\WooUpdateProduct as WooUpdateProductHooks;
use WC_Product;
use WC_Product_Variation;
use WC_Tax;
use WC_DateTime;
use WP_Post;

/**
* The Product Helper Class
Expand All @@ -28,6 +31,10 @@ class Product {
* @return bool True if name sync is enabled, false if not.
*/
public static function name_sync_enabled( WC_Product $wc_product ): bool {
if ( $wc_product instanceof WC_Product_Variation ) {
$wc_product = wc_get_product( $wc_product->get_parent_id() );
}

$meta_value = $wc_product->get_meta(
'1984_woo_dk_name_sync',
true,
Expand Down Expand Up @@ -55,6 +62,26 @@ public static function name_sync_enabled( WC_Product $wc_product ): bool {
* @return bool True if price sync is enabled, false if not.
*/
public static function price_sync_enabled( WC_Product $wc_product ): bool {
if ( $wc_product instanceof WC_Product_Variation ) {
$parent = wc_get_product( $wc_product->get_parent_id() );
if ( $parent ) {
$wc_product = $parent;
}
}

$product_dk_currency = $wc_product->get_meta(
'1984_woo_dk_dk_currency',
true,
'edit'
);

if (
( ! empty( $product_dk_currency ) ) &&
( get_woocommerce_currency() !== $product_dk_currency )
) {
return false;
}

$meta_value = $wc_product->get_meta(
'1984_woo_dk_price_sync',
true,
Expand Down Expand Up @@ -84,6 +111,13 @@ public static function price_sync_enabled( WC_Product $wc_product ): bool {
public static function quantity_sync_enabled(
WC_Product $wc_product
): bool {
if ( $wc_product instanceof WC_Product_Variation ) {
$parent = wc_get_product( $wc_product->get_parent_id() );
if ( $parent ) {
$wc_product = $parent;
}
}

$meta_value = $wc_product->get_meta(
'1984_woo_dk_stock_sync',
true,
Expand Down Expand Up @@ -199,6 +233,29 @@ public static function should_sync( WC_Product $wc_product ): bool {
return false;
}

if (
'product_variation' ===
$wc_product->get_meta( '1984_dk_woo_origin', true, 'edit' )
) {
return false;
}

$parent_id = $wc_product->get_parent_id();

if ( 0 !== $parent_id ) {
$parent = wc_get_product( $parent_id );

if (
'product_variation' === $parent->get_meta(
'1984_dk_woo_origin',
true,
'edit'
)
) {
return false;
}
}

return true;
}

Expand Down Expand Up @@ -248,4 +305,52 @@ public static function get_ledger_codes( WC_Product $wc_product ): false|object
}
return false;
}

/**
* Convert a product to variant
*
* @param int $product_id The product ID.
* @param int $parent_id The ID of the new variant's parent.
*
* @return bool True on success, false on failure.
*/
public static function convert_to_variant(
int $product_id,
int $parent_id
): int|false {
if ( 'product' !== get_post_type( $product_id ) ) {
return false;
}

$post = get_post( $product_id );
$title = $post->post_title;

if ( is_null( $post ) ) {
return false;
}

$parent = wc_get_product( $parent_id );

if ( ! $parent ) {
return false;
}

$wc_product = wc_get_product( $product_id );

if ( 'draft' === $wc_product->get_status( 'edit' ) ) {
$wc_product->set_status( 'private' );
}

$wc_product->set_parent_id( $parent_id );

// We indicate it here that this variant was originally a product.
$wc_product->update_meta_data( '1984_dk_woo_origin', 'product' );
$wc_product->update_meta_data( '1984_dk_woo_original_name', $title );

if ( 0 !== $wc_product->save() ) {
return $wc_product->get_id();
}

return false;
}
}
Loading

0 comments on commit a9a29aa

Please sign in to comment.