diff --git a/backend/app/plugins/wiaas/includes/admin/pricing/class-wiaas-admin-package-pricing.php b/backend/app/plugins/wiaas/includes/admin/pricing/class-wiaas-admin-package-pricing.php index b493291..f09555b 100644 --- a/backend/app/plugins/wiaas/includes/admin/pricing/class-wiaas-admin-package-pricing.php +++ b/backend/app/plugins/wiaas/includes/admin/pricing/class-wiaas-admin-package-pricing.php @@ -58,6 +58,7 @@ class Wiaas_Admin_Package_Pricing { $package = wc_get_product( $post->ID ); $pricing_rules = Wiaas_Package_Pricing::get_package_prices($package); $commission = Wiaas_Package_Pricing::get_package_pricing_commission($package); + $max_cost_margin = Wiaas_Package_Pricing::get_package_max_cost_margin($package); include 'views/html-package-pricing.php'; } @@ -71,7 +72,8 @@ class Wiaas_Admin_Package_Pricing { Wiaas_Package_Pricing::set_package_prices( wc_get_product( $post_id ), $_POST['wiaas_pricing_rules'], - $_POST['wiaas_pricing_rules_commision']); + $_POST['wiaas_pricing_rules_commision'], + $_POST['wiaas_max_cost_margin']); } } diff --git a/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing.php b/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing.php index 2c4d51a..ac092ff 100644 --- a/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing.php +++ b/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing.php @@ -144,6 +144,20 @@ if ( ! defined( 'ABSPATH' ) ) { }); +
+ '_wiaas_max_cost_margin', + 'name' => 'wiaas_max_cost_margin', + 'value' => $max_cost_margin, + 'label' => __( 'Max cost margin:', 'wiaas' ), + 'type' => 'number', + ) + ); + ?> +
+
cart->get_cart(); + foreach($items as $item) { + $item_id = $item['data']->get_id(); + if (wc_pb_is_bundle_container_cart_item($item) && + (Wiaas_Package_Status::get_package_status($item_id) !== Wiaas_Package_Status::AVAILABLE)){ + wc_add_notice( 'Package ' . $item['data']->get_title() . ' cannot be purchased at the moment', 'error' ); + return false; + } + } + } + /** * Process the order checkout. * @@ -87,3 +104,5 @@ class Wiaas_Checkout { } } } + +Wiaas_Checkout::init(); diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-package.php b/backend/app/plugins/wiaas/includes/class-wiaas-package.php index a7d4d32..1eb4601 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-package.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-package.php @@ -12,10 +12,38 @@ class Wiaas_Package { require_once dirname( __FILE__ ) . '/package/class-wiaas-package-option-groups.php'; require_once dirname( __FILE__ ) . '/package/class-wiaas-package-type.php'; + require_once dirname( __FILE__ ) . '/package/class-wiaas-package-status.php'; require_once dirname( __FILE__ ) . '/package/wiaas-package-functions.php'; add_filter('woocommerce_rest_prepare_product_object', array(__CLASS__, 'transform_rest_package'), 999, 3); + + add_filter('woocommerce_rest_product_object_query', array( __CLASS__, 'edit_product_query'), 10, 2); + } + + + /** + * Change product query to fetch only available packages (available status) + * @param $query + * @param $instance + */ + public static function edit_product_query($query, $request){ + if (isset($request['id'])){ + return; + } + + if (!isset($query['tax_query'])){ + $query['tax_query'] = array(); + } + + $query['tax_query'][] = + array( + 'taxonomy' => 'package_status', + 'field' => 'name', + 'terms' => Wiaas_Package_Status::AVAILABLE + ); + + return $query; } /** diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-product.php b/backend/app/plugins/wiaas/includes/class-wiaas-product.php index 4ce8b29..7197bee 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-product.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-product.php @@ -4,7 +4,7 @@ class Wiaas_Product { public static function init() { require_once dirname( __FILE__ ) . '/product/class-wiaas-product-category.php'; - require_once dirname( __FILE__ ) . '/product/class-wiaas-product-supplier.php'; + require_once dirname( __FILE__ ) . '/product/class-wiaas-product-supplier.php'; } } diff --git a/backend/app/plugins/wiaas/includes/package/class-wiaas-package-status.php b/backend/app/plugins/wiaas/includes/package/class-wiaas-package-status.php new file mode 100644 index 0000000..8a7cfd5 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/package/class-wiaas-package-status.php @@ -0,0 +1,105 @@ + _x( 'Package status', 'taxonomy general name', 'wiaas' ), + 'singular_name' => _x( 'Package status', 'taxonomy singular name', 'wiaas' ), + 'search_items' => __( 'Search Package statuses', 'wiaas' ), + 'all_items' => __( 'All Package statuses', 'wiaas' ), + 'parent_item' => __( 'Parent Package status', 'wiaas' ), + 'parent_item_colon' => __( 'Parent Package status:', 'wiaas' ), + 'edit_item' => __( 'Edit Package status', 'wiaas' ), + 'update_item' => __( 'Update Package status', 'wiaas' ), + 'add_new_item' => __( 'Add New Package status', 'wiaas' ), + 'new_item_name' => __( 'New Package status Name', 'wiaas' ), + 'menu_name' => __( 'Package status', 'wiaas' ), + ); + + $args = array( + 'hierarchical' => false, + 'labels' => $labels, + 'show_ui' => false, + 'show_admin_column' => true, + 'query_var' => true, + 'rewrite' => array( 'slug' => 'package_status' ), + ); + + register_taxonomy( 'package_status', array( 'product' ), $args ); + + + // Register available package statuses + + $statuses = [self::AVAILABLE, self::INVALID_MARGIN, self::INVALID_TEMPLATE]; + + foreach ($statuses as $status) { + wp_insert_term($status, 'package_status'); + } + } + + /** + * Retrieve available wiaas package statuses + * @return array + */ + public static function get_available_package_statuses() { + $statuses = get_terms( array( + 'taxonomy' => 'package_status', + 'hide_empty' => false, + ) ); + + return array_map(function($status) { + return $status->name; + }, $statuses); + } + + /** + * Retrieve package status for provided package id + * @param $package_id + * + * @return null + */ + public static function get_package_status($package_id) { + $terms = wp_get_object_terms($package_id, 'package_status'); + $package_status = isset($terms[0]) ? $terms[0]->name : null; + return $package_status; + } + + /** + * Set package status for provided package id + * @param $package_id + * @param $status + */ + public static function set_package_status($package_id, $status) { + + wp_delete_object_term_relationships( $package_id, 'package_status' ); + + if (isset($status)) { + wp_set_object_terms($package_id, $status, 'package_status', false); + } + } +} + +Wiaas_Package_Status::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-pricing.php b/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-pricing.php index 7aea921..7c9fd30 100644 --- a/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-pricing.php +++ b/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-pricing.php @@ -51,6 +51,8 @@ class Wiaas_Package_Pricing { public static function init() { add_filter('woocommerce_bundle_price_html', array( __CLASS__, 'get_package_price_html' ), 10, 2); + + add_action('woocommerce_update_product', array(__CLASS__, 'on_product_update' ), 10, 1 ); } public static function get_package_price_html($price_html, $package) { @@ -101,21 +103,46 @@ class Wiaas_Package_Pricing { return self::_get_package_pricing_commision($package); } + public static function get_package_max_cost_margin($package){ + return self::_get_package_max_cost_margin($package); + } + /** * Persist payment prices configuration for package * @param $package * @param $pricing_rules */ - public static function set_package_prices($package, $pricing_rules, $commision) { + public static function set_package_prices($package, $pricing_rules, $commision, $max_cost_margin) { if ( isset( $pricing_rules ) ) { $package->update_meta_data( '_wiaas_pricing_rules', $pricing_rules ); $package->update_meta_data('_package_pricing_commision', $commision, true); + $package->update_meta_data('_package_max_cost_margin', $max_cost_margin, true); } else { $package->delete_meta_data( '_wiaas_pricing_rules' ); } $package->save_meta_data(); } + /** + * Executes when woocommerce product is updated + */ + public static function on_product_update($product_id) { + $product = wc_get_product($product_id); + + if ($product->get_type() === WC_Product_Simple::get_type()){ + $product_price = Wiaas_Product_Pricing::get_product_price($product); + + $packages_containing_updated_product = wc_pb_get_bundled_product_map( $product ); + + foreach($packages_containing_updated_product as $index => $package_id){ + $package = new WC_Product_Bundle($package_id); + self::_validate_package($package); + } + }else if ($product->get_type() === WC_Product_Bundle::get_type()){ + self::_validate_package($product); + } + } + // PRIVATE private static function _get_package_prices($package) { @@ -164,6 +191,26 @@ class Wiaas_Package_Pricing { return (float) $commision; } + + private static function _get_package_max_cost_margin($package) { + $max_cost_margin = $package->get_meta( '_package_max_cost_margin', true); + + if (!isset($max_cost_margin) || $max_cost_margin === '') { + return 0; + } + + return (float) $max_cost_margin; + } + + private static function _validate_package($package){ + $package_total_cost = Wiaas_Pricing::get_package_total_cost($package); + $package_max_cost_margin = Wiaas_Package_Pricing::get_package_max_cost_margin($package); + if (($package_max_cost_margin != 0) && ($package_total_cost > $package_max_cost_margin)){ + Wiaas_Package_Status::set_package_status($package->get_id(), Wiaas_Package_Status::INVALID_MARGIN); + }else{ + Wiaas_Package_Status::set_package_status($package->get_id(), Wiaas_Package_Status::AVAILABLE); + } + } } Wiaas_Package_Pricing::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/product/class-wiaas-product-supplier.php b/backend/app/plugins/wiaas/includes/product/class-wiaas-product-supplier.php index eeb71de..ecffddb 100644 --- a/backend/app/plugins/wiaas/includes/product/class-wiaas-product-supplier.php +++ b/backend/app/plugins/wiaas/includes/product/class-wiaas-product-supplier.php @@ -48,8 +48,16 @@ class Wiaas_Product_Supplier { */ public static function on_organization_added($organization_id) { $organization = get_term_by('id', $organization_id, 'wiaas-user-organization'); - $supplier = wp_insert_term($organization->name, 'supplier'); - add_term_meta($supplier['term_id'], 'organisation_id', $organization->term_id); + + $supplier = term_exists($organization->slug, 'supplier'); + + if (! $supplier) { + $supplier = wp_insert_term($organization->name, 'supplier', array( + 'slug' => $organization->slug + )); + } + + add_term_meta($supplier['term_id'], 'organisation_id', $organization->term_id); } } diff --git a/backend/app/plugins/wiaas/tests/unit-tests/package/class-wiaas-package-status.php b/backend/app/plugins/wiaas/tests/unit-tests/package/class-wiaas-package-status.php new file mode 100644 index 0000000..f722379 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/unit-tests/package/class-wiaas-package-status.php @@ -0,0 +1,120 @@ +assertInstanceOf(WP_Taxonomy::class, $taxonomy); + + $package_statuses = Wiaas_Package_Status::get_available_package_statuses(); + + $this->assertNotEmpty($package_statuses); + + $this->assertContains(Wiaas_Package_Status::AVAILABLE, $package_statuses); + } + + /** + * @covers Wiaas_Package_Type::set_package_status() + * @covers Wiaas_Package_Type::get_package_status() + */ + function test_adding_package_status() { + $package = $this->create_new_package(); + + Wiaas_Package_Status::set_package_status($package->get_id(), Wiaas_Package_Status::AVAILABLE); + + $package_status = Wiaas_Package_Status::get_package_status($package->get_id()); + + $this->assertNotNull($package_status); + $this->assertEquals($package_status, Wiaas_Package_Status::AVAILABLE); + } + + /** + * Test package status update on simple product price update + */ + function test_package_status_update_on_simple_product_price_update() { + $product1 = $this->create_new_product(20); + $this->add_product_category($product1, 'hardware'); + + $product2 = $this->create_new_product(20); + $this->add_product_category($product2, 'software'); + + $package = $this->create_new_package(); + + $this->add_products_to_package($package, array( $product1, $product2)); + + $pricing_rules = array( + 'purchase' => array( + 'minimal_fixed_price' => 100, + 'principal_amount' => 0, + 'minimal_services_price' => 0 + ), + 'purchase_24' => array( + 'minimal_fixed_price' => 100, + 'principal_amount' => 0, + 'minimal_services_price' => 100 + ), + 'managed_36' => array( + 'minimal_fixed_price' => 100, + 'principal_amount' => 100, + 'minimal_services_price' => 100 + ) + ); + $commision = 50; + $cost_margin = 100; + + Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision, $cost_margin); + $this->assertEquals(Wiaas_Package_Status::get_package_status($package)->get_id(), Wiaas_Package_Status::AVAILABLE); + + $product1->set_price(1000); + $this->assertEquals(Wiaas_Package_Status::get_package_status($package)->get_id(), Wiaas_Package_Status::MARGIN_EXCEEDED); + + } + + /** + * Test package status update on cost margin update + */ + function test_package_status_update_on_margin_cost_update() { + $product1 = $this->create_new_product(20); + $this->add_product_category($product1, 'hardware'); + + $product2 = $this->create_new_product(20); + $this->add_product_category($product2, 'software'); + + $package = $this->create_new_package(); + + $this->add_products_to_package($package, array( $product1, $product2)); + + $pricing_rules = array( + 'purchase' => array( + 'minimal_fixed_price' => 100, + 'principal_amount' => 0, + 'minimal_services_price' => 0 + ), + 'purchase_24' => array( + 'minimal_fixed_price' => 100, + 'principal_amount' => 0, + 'minimal_services_price' => 100 + ), + 'managed_36' => array( + 'minimal_fixed_price' => 100, + 'principal_amount' => 100, + 'minimal_services_price' => 100 + ) + ); + $commision = 50; + $cost_margin = 0; + + Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision, $cost_margin); + $this->assertEquals(Wiaas_Package_Status::get_package_status($package)->get_id(), Wiaas_Package_Status::AVAILABLE); + + $cost_margin = 1; + Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision, $cost_margin); + $this->assertEquals(Wiaas_Package_Status::get_package_status($package)->get_id(), Wiaas_Package_Status::MARGIN_EXCEEDED); + + } +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-pricing.php b/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-pricing.php index 648b2dc..ab5c693 100644 --- a/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-pricing.php +++ b/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-pricing.php @@ -29,8 +29,9 @@ class Wiaas_Package_Pricing_Test extends Wiaas_Unit_Test_Case { ); $commision = 60; + $cost_margin = 0; - Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision); + Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision, $cost_margin); $configured_prices = Wiaas_Package_Pricing::get_package_prices($package); diff --git a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-pricing.php b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-pricing.php index 5d62fdd..83ad6d0 100644 --- a/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-pricing.php +++ b/backend/app/plugins/wiaas/tests/unit-tests/test-wiaas-pricing.php @@ -31,7 +31,8 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { ) ); $commision = 50; - Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision); + $cost_margin = 0; + Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision, $cost_margin); $expected_prices = array( 'purchase' => array( @@ -229,7 +230,8 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { ) ); $commision = 50; - Wiaas_Package_Pricing::set_package_prices($addon_package, $pricing_rules, $commision); + $cost_margin = 0; + Wiaas_Package_Pricing::set_package_prices($addon_package, $pricing_rules, $commision, $cost_margin); Wiaas_Package_Addon::set_package_addons($package, array($addon_package->get_id())); @@ -306,7 +308,8 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { ) ); $commision = 50; - Wiaas_Package_Pricing::set_package_prices($option_package, $pricing_rules, $commision); + $cost_margin = 0; + Wiaas_Package_Pricing::set_package_prices($option_package, $pricing_rules, $commision, $cost_margin); Wiaas_Package_Option_Groups::set_package_option_groups($package, array( 'id' => 'option', diff --git a/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php b/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php index d4c64b5..f83ff95 100644 --- a/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php +++ b/backend/app/plugins/wiaas/tests/wiaas-unit-test-case.php @@ -26,6 +26,8 @@ class Wiaas_Unit_Test_Case extends WP_UnitTestCase { Wiaas_Package_Type::register_package_type_taxonomy(); Wiaas_Order_Project::register_order_project_taxonomy(); + + Wiaas_Product_Supplier::register_supplier_taxonomy(); define('WP_TEST_IN_PROGRESS',true); }