diff --git a/backend/app/plugins/wiaas/assets/css/package.css b/backend/app/plugins/wiaas/assets/css/package.css index 08fe4cc..3cb3f82 100644 --- a/backend/app/plugins/wiaas/assets/css/package.css +++ b/backend/app/plugins/wiaas/assets/css/package.css @@ -128,4 +128,9 @@ #your-profile label[for="role"], #your-profile label[for="url"],#your-profile #role, #your-profile #url{ display: none; +} + +#adminmenu #toplevel_page_wiaas-cl-packages div.wp-menu-image::before { + font-family: WooCommerce!important; + content: '\e006'; } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/assets/css/wiaas-admin-cl.css b/backend/app/plugins/wiaas/assets/css/wiaas-admin-cl.css new file mode 100644 index 0000000..50e9ff3 --- /dev/null +++ b/backend/app/plugins/wiaas/assets/css/wiaas-admin-cl.css @@ -0,0 +1,7 @@ +#posts-filter .tablenav .actions { + display: none; +} + +#menu-posts-product .wp-submenu li:last-child { + display: none; +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/assets/js/wiaas-admin-cl-packages.js b/backend/app/plugins/wiaas/assets/js/wiaas-admin-cl-packages.js new file mode 100644 index 0000000..55332cb --- /dev/null +++ b/backend/app/plugins/wiaas/assets/js/wiaas-admin-cl-packages.js @@ -0,0 +1,71 @@ +jQuery(document).ready(function ($) { + + $('#tabs').each(function() { + var disabled = $( this ).data('disabled') || ''; + + $( this ).tabs({ + disabled: [ disabled ] + }); + }); + + $('#wiaas_add_cl_customer_extras').click(function(e) { + e.preventDefault(); + + var customer_id = $('#wiaas_cl_customers').val(); + + if (!customer_id || customer_id === '0') { + return; + } + + $.post(window.ajaxurl, { + action: 'wiaas_create_cl_customer_extras', + _ajax_nonce: $('#wiaas_create_cl_customer_extras_nonce').val(), + customer_id: customer_id, + package_id: $('#wiaas_cl_package_id').val() + }).done( function (result) { + $('#tabs-2').append(result); + + $('#wiaas_cl_customer_' + customer_id).prop( 'disabled', true ); + }); + + $('#wiaas_cl_customers').val('0'); + }); + + $('#wiaas_package_extras').delegate('.wiaas_remove_cl_extras', 'click', function(e) { + e.preventDefault(); + + var customer_id = $( this ).data('customer_id'); + + $('#extras_customer_' + customer_id).remove(); + + $('#wiaas_cl_customer_' + customer_id).prop( 'disabled', false ); + + $('#wiaas_cl_customers').val('0'); + }); + + $('#wiaas_package_extras').delegate('.wiaas-cl-extra-input', 'change', function(e) { + e.preventDefault(); + + var val = parseFloat($( this ).val()); + var target = '#' + $( this).data('target'); + + if (isNaN(val)) { + + $(target).val('Invalid!'); + + return; + } + + var type = $( this).data('type'); + + if (type === 'fixed') { + $(target).text( $(target).data('base') + val); + } + + if (type === 'recurrent' || type === 'services') { + $(target).data(type, val); + + $(target).text( $(target).data('base') + $(target).data('recurrent') + $(target).data('services')); + } + }); +}); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/admin/admin-cl/class-wiaas-admin-cl-packages.php b/backend/app/plugins/wiaas/includes/admin/admin-cl/class-wiaas-admin-cl-packages.php new file mode 100644 index 0000000..9176ce2 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/admin/admin-cl/class-wiaas-admin-cl-packages.php @@ -0,0 +1,260 @@ +id === 'admin_page_wiaas-cl-product') { + + error_log('set parent'); + + $parent_file = 'edit.php?post_type=product'; + } + } + + public static function output_package() { + wp_enqueue_script( 'jquery-ui-tabs' ); + + $package_id = absint( $_GET['cl_package_id'] ); + + $package = wc_get_product($package_id); + + if (!$package) { + return; + } + + if (! empty($_POST['wiaas_save_cl_extras_nonce']) && ! empty($_POST['cl_extras'])) { + if (wp_verify_nonce($_POST['wiaas_save_cl_extras_nonce'], 'wiaas_save_cl_extras')) { + self::_handle_cl_extras_update($package_id); + } + } + + $bundled_items = $package->get_bundled_items(); + + $bundled_items_per_category = array(); + foreach ($bundled_items as $bundled_item) { + $category = Wiaas_Product_Category::get_category($bundled_item->product); + if (isset($category)) { + if ($category ==='hardware' || $category === 'software') { + $category = 'products'; + } + $bundled_items_per_category[$category] ?: array(); + $bundled_items_per_category[$category][] = $bundled_item; + } + } + + $configured_prices = Wiaas_Package_Pricing::get_package_prices($package); + + $cl_id = wiaas_get_current_user_organization_id(); + + $cl_extras = Wiaas_Package_CL_Pricing::get_extras($cl_id, $package_id); + + $has_default_cl_extras = ! empty($cl_extras); + + // default values for catalogue package + if (! $has_default_cl_extras) { + $cl_extras = array(); + + foreach ($configured_prices as $type => $configured_price) { + $cl_extras[$type.'_default'] = array( + 'visible' => true, + 'fixed' => 0, + 'services' => 0, + 'recurrent' => 0 + ); + } + } + + $package_cl_extra_types = array_keys($cl_extras); + + $customer_ids_with_extras = array(); + foreach ($package_cl_extra_types as $package_cl_extra_type) { + $customer_id_with_extras = explode('_customer_', $package_cl_extra_type)[1]; + + if (isset($customer_id_with_extras) && ($customer_id_with_extras = absint($customer_id_with_extras)) > 0) { + $customer_ids_with_extras[] = $customer_id_with_extras; + } + } + $customer_ids_with_extras = array_unique($customer_ids_with_extras); + + require 'views/html-cl-package-details.php'; + } + + + /** + * @section Customize display of list table products for commercial lead + */ + + /** + * Define columns for commercial lead view + * @param array $columns + * + * @return array + */ + public static function define_list_table_products_columns($columns) { + $cl_columns = array(); + + $cl_columns['thumb'] = $columns['thumb']; + $cl_columns['wiaas_cl_name'] = $columns['name']; + $cl_columns['taxonomy-package_type'] = __('Type', 'wiaas'); + $cl_columns['taxonomy-package_status'] = __('Status', 'wiaas'); + $cl_columns['taxonomy-product_country'] = $columns['taxonomy-product_country']; + $cl_columns['date'] = $columns['date']; + + return $cl_columns; + } + + /** + * Hide list table products bulk actions for commercial lead view + * + * @return array + */ + public static function define_list_table_products_bulk_actions() { + return array(); + } + + /** + * Hide list table products views for commercial lead view + * + * @return array + */ + public static function define_list_table_products_views() { + return array(); + } + + /** + * Show only ID in table products views for commercial lead view + * + * @return array + */ + public static function define_list_table_products_row_actions($actions, $post) { + if ($post->post_type === 'product') { + return array( 'id' => sprintf( __( 'ID: %d', 'woocommerce' ), $post->ID ) ); + } + + return $actions; + } + + /** + * Define custom primary column in list table products for commercial lead view + * + * @param $default + * @param $screen_id + * + * @return string + */ + public static function define_list_table_products_primary_column($default, $screen_id) { + if ( 'edit-product' === $screen_id ) { + return 'wiaas_cl_name'; + } + return $default; + } + + public static function render_list_table_products_columns($column, $post_id) { + if ($column === 'wiaas_cl_name') { + + $package = wc_get_product($post_id); + + $edit_link = admin_url( 'edit.php?post_type=product&page=wiaas-cl-package&cl_package_id=' . absint( $package->get_id() ) ); + + echo '' . esc_html( $package->get_title() ) . ''; + } + } + + + + + // PRIVATE HANDLERS + + private static function _handle_cl_extras_update($package_id) { + $cl_extras = wp_unslash($_POST['cl_extras']); + + $pay_types = array_keys(Wiaas_Package_Pricing::get_available_pay_types()); + + $posted_cl_extras = array(); + + foreach ($cl_extras as $cl_extra) { + + $customer_id = isset($cl_extra['customer']) ? absint($cl_extra['customer']) : 0; + $type = sanitize_key($cl_extra['type']); + + $fixed_extra = isset($cl_extra['fixed']) ? floatval($cl_extra['fixed']) : 0; + $services_extra = isset($cl_extra['services']) ? floatval($cl_extra['services']) : 0; + $recurrent_extra = isset($cl_extra['recurrent']) ? floatval($cl_extra['recurrent']) : 0; + + $extra_type = $customer_id > 0 ? $type.'_customer_'.$customer_id : $type.'_default'; + + if (in_array($type, $pay_types)) { + $posted_cl_extras[$extra_type] = array( + 'type' => $type, + 'visible' => $cl_extra['visible'] === 'on', + 'fixed' => $fixed_extra, + 'services' => $services_extra, + 'recurrent' => $recurrent_extra, + ); + } + } + + Wiaas_Package_CL_Pricing::set_extras( + wiaas_get_current_user_organization_id(), + $package_id, + $posted_cl_extras + ); + } +} + +Wiaas_Admin_CL_Packages::init(); diff --git a/backend/app/plugins/wiaas/includes/admin/admin-cl/views/html-cl-package-details.php b/backend/app/plugins/wiaas/includes/admin/admin-cl/views/html-cl-package-details.php new file mode 100644 index 0000000..d2b95b5 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/admin/admin-cl/views/html-cl-package-details.php @@ -0,0 +1,237 @@ + + + + + + +
+
+
+
+
+
+
+
+
+ $category_bundled_items) { + echo sprintf( + '%s (%s)', + esc_attr( $category ), + esc_attr(count($category_bundled_items)) ); + foreach ($category_bundled_items as $bundled_item) { + $title = $bundled_item->product->get_title(); + echo sprintf( '

%s x %s

', esc_attr($bundled_item->get_quantity('max')), esc_attr( $title ) ); + } + } + ?> +
+
+
+
+
+
+ +
+ +
+
+
+
+

get_name(); ?>

+
+
+
+
+ + get_short_description())) { + ?> +
+ get_short_description(), 'content', array( + '_content_editor_dfw' => $_content_editor_dfw, + 'drag_drop_upload' => false, + 'media_buttons' => false, + 'quicktags' => false, + 'tabfocus_elements' => 'content-html', + 'tinymce' => array( + 'resize' => false, + 'wp_autoresize_on' => true, + 'add_unload_trigger' => false, + 'wp_keep_scroll_position' => ! $is_IE, + 'readonly'=> true, + 'toolbar' => false, + ), + ) ); ?> +
+ + +
+
+
+
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
    +
  • |
  • +
  • +
+ +
+ + + +
+ + + +
+
+ +
+ + + +
+ + +
+ + + + +
+
+ +
+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/admin/admin-cl/views/html-cl-package-prices.php b/backend/app/plugins/wiaas/includes/admin/admin-cl/views/html-cl-package-prices.php new file mode 100644 index 0000000..cb3220f --- /dev/null +++ b/backend/app/plugins/wiaas/includes/admin/admin-cl/views/html-cl-package-prices.php @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + $configured_price) { + + $extra_type = isset($customer_id) ? $type.'_customer_'.$customer_id : $type.'_default'; + + ?> + + + + + + + + + + + + + + + +
+ '. esc_html(wiaas_get_organization_name($customer_id)). ''; + } + ?> + + + + +
+ + +
+ + +
+
+ + + 0) { + echo sprintf( '(%s for services)', esc_attr( $configured_price['minimal_services_price'] ) ); + } + ?> + +
+
+
+ + +
+ 0) { + ?> +
+ + + +
+ +
+ + + +
+
+
= + + + +
+
= + + +
+
+ + type="checkbox" + > +
diff --git a/backend/app/plugins/wiaas/includes/admin/admin-cl/wiaas-admin-cl-packages-ajax.php b/backend/app/plugins/wiaas/includes/admin/admin-cl/wiaas-admin-cl-packages-ajax.php new file mode 100644 index 0000000..815f7c8 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/admin/admin-cl/wiaas-admin-cl-packages-ajax.php @@ -0,0 +1,31 @@ + $configured_price) { + $cl_extras[$type.'_customer_'.$customer_id] = array( + 'type' => $type, + 'visible' => true, + 'fixed' => 0, + 'services' => 0, + 'recurrent' => 0 + ); + } + + require_once 'views/html-cl-package-prices.php'; + + die(); + +} \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-cl.php b/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-cl.php new file mode 100644 index 0000000..efd1d3e --- /dev/null +++ b/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-cl.php @@ -0,0 +1,40 @@ +roles[0]; + + if ($role === 'commercial_lead') { + + require_once dirname( __FILE__ ) . '/admin-cl/class-wiaas-admin-cl-packages.php'; + + require_once dirname( __FILE__ ) . '/admin-cl/wiaas-admin-cl-packages-ajax.php'; + + add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 ); + + } + } + + public static function enqueue_scripts() { + $plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) ); + + wp_enqueue_script( 'wiaas_admin_cl_packages', $plugin_url . '/assets/js/wiaas-admin-cl-packages.js' ); + + wp_enqueue_style( 'wiaas_admin_cl', $plugin_url . '/assets/css/wiaas-admin-cl.css' ); + } +} + +Wiaas_Admin_CL::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-organization.php b/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-organization.php index b0b58f8..5889ae9 100644 --- a/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-organization.php +++ b/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-organization.php @@ -26,6 +26,13 @@ class Wiaas_Admin_Organization { return array(); } + /** + * Render user organization roles as available user roles on user list + * @param $role_list + * @param $user + * + * @return mixed + */ public static function get_role_list_for_user($role_list, $user) { $organization_id = wiaas_get_user_organization_id($user->ID); @@ -44,6 +51,13 @@ class Wiaas_Admin_Organization { return $role_list; } + /** + * Customize columns for users table list view + * + * @param array $defaults + * + * @return array + */ public static function manage_users_table_columns( $defaults = array() ) { $defaults['role'] = __('Roles', 'wiaas'); diff --git a/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-package.php b/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-package.php index bc8c90e..960555e 100644 --- a/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-package.php +++ b/backend/app/plugins/wiaas/includes/admin/class-wiaas-admin-package.php @@ -7,16 +7,10 @@ if ( ! defined( 'ABSPATH' ) ) { class Wiaas_Admin_Package { public static function init() { - add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 ); require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-linked-packages.php'; require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-package-types.php'; } - - public static function enqueue_scripts() { - $plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) ); - wp_enqueue_style( 'wiaas_admin_styles', $plugin_url . '/assets/css/package.css' ); - } } Wiaas_Admin_Package::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing-rule-recurrent-price.php b/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing-rule-recurrent-price.php index 0b3b7d3..1a70dcc 100644 --- a/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing-rule-recurrent-price.php +++ b/backend/app/plugins/wiaas/includes/admin/pricing/views/html-package-pricing-rule-recurrent-price.php @@ -6,13 +6,7 @@ if ( ! defined( 'ABSPATH' ) ) { 0 && $pay_type['package_pay_period'] > 0) { - $value += wiaas_PMT( - Wiaas_Pricing::INTEREST_RATE, - $pay_type['package_pay_period'], - $pricing_rule['principal_amount']); -} +$value = $pricing_rule['minimal_recurrent_price']; ?> diff --git a/backend/app/plugins/wiaas/includes/api/class-wiaas-package-api.php b/backend/app/plugins/wiaas/includes/api/class-wiaas-package-api.php new file mode 100644 index 0000000..cf3eea6 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/api/class-wiaas-package-api.php @@ -0,0 +1,79 @@ + WP_REST_Server::READABLE, + 'callback' => array(__CLASS__, 'get_customer_commercial_leads'), + 'permission_callback' => 'is_user_logged_in' + ) ); + } + + // TODO: Handle this when assigment of customer to commercial lead is done + public static function get_customer_commercial_leads() { + $commercial_leads = array(); + + foreach (wiaas_get_commercial_leads() as $id => $name) { + $commercial_leads[] = array( + 'id' => $id, + 'name' => $name + ); + } + + return rest_ensure_response($commercial_leads); + } + + /** + * Filter woocommerce REST API query so only valid wiaas packages are returned to the customer + * + * @param $args + * @param $request + * + * @return mixed + */ + public static function filter_packages($args, $request) { + + if ( empty($query['tax_query']) ){ + $query['tax_query'] = array(); + } + + // Retrieve only packages with available package status + $query['tax_query'][] = array( + 'taxonomy' => 'package_status', + 'field' => 'name', + 'terms' => Wiaas_Package_Status::AVAILABLE + ); + + + $commercial_lead_id = absint($request['cl_id']); + + $customer_id = wiaas_get_current_user_organization_id(); + + $pay_types = array_keys(Wiaas_Package_Pricing::get_available_pay_types()); + + $price_search_terms = array(); + foreach ($pay_types as $pay_type) { + $price_search_terms[] = '_' . $commercial_lead_id . '_' . $pay_type . '_default'; + $price_search_terms[] = '_' . $commercial_lead_id . '_' . $pay_type . '_customer_' . $customer_id; + } + + $args['tax_query'][] = array( + 'taxonomy' => '_wiaas_shop_prices', + 'terms' => $price_search_terms, + 'field' => 'slug' + ); + + return $args; + } +} + +Wiaas_Package_API::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-access-management.php b/backend/app/plugins/wiaas/includes/class-wiaas-access-management.php new file mode 100644 index 0000000..ca4f6a3 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/class-wiaas-access-management.php @@ -0,0 +1,51 @@ +post_type !== 'product') { + return; + } + + $product = wc_get_product($post_id); + + $admin_access_group = Groups_Group::read_by_name('admin'); + + $access_group_ids = array(); + + if ($admin_access_group) { + $access_group_ids[] = $admin_access_group->group_id; + } + + // allow commercial lead to see published bundle products + $cl_access_group = Groups_Group::read_by_name('commercial_lead'); + + if ($product->get_type() === 'bundle' && + $product->get_status() === 'publish' && + $cl_access_group) { + $access_group_ids[] = $cl_access_group->group_id; + } + + Groups_Post_Access::update( + array( + 'post_id' => $product->get_id(), + 'groups_read' => $access_group_ids + ) ); + + } +} + +Wiaas_Access_Management::init(); diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-admin.php b/backend/app/plugins/wiaas/includes/class-wiaas-admin.php index 05c12ca..096f2e4 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-admin.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-admin.php @@ -20,13 +20,17 @@ class Wiaas_Admin { // Admin organization interface require_once dirname(__FILE__) . '/admin/class-wiaas-admin-organization.php'; + require_once dirname(__FILE__) . '/admin/class-wiaas-admin-cl.php'; + add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 ); } public static function enqueue_scripts() { $plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) ); + wp_enqueue_style( 'wiaas_admin_menu', $plugin_url . '/assets/css/menu.css' ); + wp_enqueue_style( 'wiaas_admin_packages', $plugin_url . '/assets/css/package.css' ); } } diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-api.php b/backend/app/plugins/wiaas/includes/class-wiaas-api.php index 7f5eadf..a394380 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-api.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-api.php @@ -43,6 +43,8 @@ class Wiaas_API { include_once dirname( __FILE__ ) . '/api/class-wiaas-order-projects-api.php'; + include_once dirname( __FILE__ ) . '/api/class-wiaas-package-api.php'; + // API functions include_once dirname( __FILE__ ) . '/api/wiaas-api-functions.php'; @@ -55,7 +57,8 @@ class Wiaas_API { 'Wiaas_Document_API', 'Wiass_REST_User_API', 'Wiaas_REST_Customer_API', - 'Wiaas_Order_Projects_API' + 'Wiaas_Order_Projects_API', + 'Wiaas_Package_API' ); foreach ( $controllers as $controller ) { diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-cart.php b/backend/app/plugins/wiaas/includes/class-wiaas-cart.php index 8968b62..ba573f6 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-cart.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-cart.php @@ -144,8 +144,12 @@ class Wiaas_Cart { // Retrieve package country $country = Wiaas_Countries::get_package_country($package); - // Retrieve package price - $package_prices = Wiaas_Pricing::get_standard_package_customer_prices($package); + // TODO: Change this so commercial lead is sent via request + $customer_id = wiaas_get_current_user_organization_id(); + $commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0]; + + // Retrieve package price + $package_prices = Wiaas_Pricing::get_standard_package_customer_prices($package, $customer_id, $commercial_lead_id); $selected_price_index = array_search($price_id, array_column($package_prices, 'id')); // Initialize additional cart item data for wiaas packages @@ -644,6 +648,10 @@ class Wiaas_Cart { $addon_items_keys = array(); $option_items_keys = array(); + // TODO: Change this so commercial lead is sent via request + $customer_id = wiaas_get_current_user_organization_id(); + $commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0]; + // Try adding package addons to cart foreach ($addons_ids as $addon_id) { //Check if addon package exists @@ -652,8 +660,13 @@ class Wiaas_Cart { throw new Exception( __( 'Sorry, additional package does not exist.', 'wiaas' ) ); } - // Retrieve addon package price - $package_prices = Wiaas_Pricing::get_addon_package_customer_price($addon_package, $parent_item['data']); + // Retrieve addon package price + $package_prices = Wiaas_Pricing::get_addon_package_customer_price( + $addon_package, + $parent_item['data'], + $customer_id, + $commercial_lead_id + ); $selected_price_index = array_search($price_id, array_column($package_prices, 'id')); // Initialize additional cart item data for wiaas addon packages @@ -684,8 +697,12 @@ class Wiaas_Cart { throw new Exception( __( 'Sorry, option package does not exist.', 'wiaas' ) ); } - // Retrieve option package price - $package_prices = Wiaas_Pricing::get_option_package_customer_price($option_package, $parent_item['data']); + // Retrieve option package price + $package_prices = Wiaas_Pricing::get_option_package_customer_price( + $option_package, + $parent_item['data'], + $customer_id, + $commercial_lead_id); $selected_price_index = array_search($price_id, array_column($package_prices, 'id')); // Retrieve option package group name diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php b/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php index e1a4779..7adca2c 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-db-update.php @@ -12,12 +12,15 @@ class Wiaas_DB_Update { '20180813134511' => 'wiaas_db_update_enable_order_numbers', '20180826153509' => 'wiaas_create_broker_access_group', '20180911101010' => 'wiaas_db_setup_exclusive_taxonomies', - '20180912101010' => 'wiaas_db_setup_default_cl', '20181003164100' => 'wiaas_db_setup_customer_capabilities', - '201810031644700' => 'wiaas_db_update_create_default_roles', - '201810101644700' => 'wiaas_db_import_aam_role_settings', '201810111644700' => 'wiaas_db_update_add_organization_info_ui_fields', - '201810121644700' => 'wiaas_db_update_add_user_organization_ui_fields' + '201810121644700' => 'wiaas_db_update_add_user_organization_ui_fields', + '201810171645700' => 'wiaas_db_update_create_default_roles', + '201810171745700' => 'wiaas_db_import_aam_role_settings', + '201810173045700' => 'wiaas_db_update_update_commercial_lead_capabilities', + '201810173145700' => 'wiaas_db_update_update_supplier_capabilities', + '201810173245700' => 'wiaas_db_update_update_admin_capabilities', + '201810173345700' => 'wiaas_create_role_access_groups' ); public static function execute() { diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-package.php b/backend/app/plugins/wiaas/includes/class-wiaas-package.php index 4f12ca4..6b4b49a 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-package.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-package.php @@ -17,33 +17,6 @@ class Wiaas_Package { 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; } /** @@ -120,6 +93,9 @@ class Wiaas_Package { * @return array */ private static function _append_additional_packages($data, $package, $request) { + // TODO: Change this so commercial lead is sent via request + $customer_id = wiaas_get_current_user_organization_id(); + $commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0]; $data['additional_packages'] = array(); $addons = Wiaas_Package_Addon::get_package_addons($package); @@ -128,7 +104,7 @@ class Wiaas_Package { 'id' => $addon->get_id(), 'name' => $addon->get_name(), 'description' => $addon->get_description(), - 'prices' => Wiaas_Pricing::get_addon_package_customer_price($addon, $package), + 'prices' => Wiaas_Pricing::get_addon_package_customer_price($addon, $package, $customer_id, $commercial_lead_id), ); } @@ -149,7 +125,7 @@ class Wiaas_Package { 'name' => $option_package->get_name(), 'description' => $option_package->get_description(), 'default' => $default_option_id === $option_package->get_id(), - 'prices' => Wiaas_Pricing::get_option_package_customer_price($option_package, $package), + 'prices' => Wiaas_Pricing::get_option_package_customer_price($option_package, $package, $customer_id, $commercial_lead_id), ); } } @@ -166,7 +142,11 @@ class Wiaas_Package { * @return array */ private static function _append_package_prices($data, $package, $request) { - $data['prices'] = Wiaas_Pricing::get_standard_package_customer_prices($package); + // TODO: Change this so commercial lead is sent via request + $customer_id = wiaas_get_current_user_organization_id(); + $commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0]; + + $data['prices'] = Wiaas_Pricing::get_standard_package_customer_prices($package, $customer_id, $commercial_lead_id); return $data; } diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-pricing.php b/backend/app/plugins/wiaas/includes/class-wiaas-pricing.php index 2134676..2555030 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-pricing.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-pricing.php @@ -1,7 +1,7 @@ get_bundled_items(); + foreach ($bundled_items as $bundled_item) { - $bundled_items = $package->get_bundled_items(); - foreach ($bundled_items as $bundled_item) { + $product = $bundled_item->product; + $product_cat = Wiaas_Product_Category::get_category($product); - $product = $bundled_item->product; - $product_cat = Wiaas_Product_Category::get_category($product); + if (!isset($total_cost_per_category[$product_cat])) { + $total_cost_per_category[$product_cat] = 0; + } - if (!isset($total_cost_per_category[$product_cat])) { - $total_cost_per_category[$product_cat] = 0; - } + $total_item_cost = self::get_product_total_cost($product) * $bundled_item->get_quantity(); - $total_item_cost = self::get_product_total_cost($product) * $bundled_item->get_quantity(); + if (Wiaas_Product_Category::is_installation($product)) { + $total_cost_per_category[$product_cat] = $total_cost_per_category[$product_cat] < $total_item_cost ? + $total_item_cost : + $total_cost_per_category[$product_cat]; + } else { + $total_cost_per_category[$product_cat] += $total_item_cost; + } + } - if (Wiaas_Product_Category::is_installation($product)) { - $total_cost_per_category[$product_cat] = $total_cost_per_category[$product_cat] < $total_item_cost ? - $total_item_cost : - $total_cost_per_category[$product_cat]; - } else { - $total_cost_per_category[$product_cat] += $total_item_cost; - } - } + return array_sum(array_values($total_cost_per_category)); + } - return array_sum(array_values($total_cost_per_category)); - } + /** + * Calculates customer prices for wiaas standard package + * @param WC_Product_Bundle $package + * @param int $customer_id + * @param int $commercial_lead_id + * + * @return array + */ + public static function get_standard_package_customer_prices($package, $customer_id, $commercial_lead_id) { - /** - * Calculates customer price for wiaas standard package - * @param $package - * - * @return array - */ - public static function get_standard_package_customer_prices($package) { + return self::_get_package_customer_prices( + $package, + (100 - Wiaas_Package_Pricing::get_package_pricing_commission($package)) / 100, // commercial lead commission + self::get_package_total_cost($package), // total cost of package items + $customer_id, + $commercial_lead_id); - $is_same_company_as_cl = self::_is_customer_same_company_as_cl(); - $package_prices = Wiaas_Package_Pricing::get_package_prices($package); - $cl_commision = (100 - Wiaas_Package_Pricing::get_package_pricing_commission($package)) / 100; - $total_cost = self::get_package_total_cost($package); + } - $customer_package_prices = array(); + /** + * Calculates customer prices for wiaas addon package + * + * @param WC_Product_Bundle $addon_package + * @param WC_Product_Bundle $parent_package + * @param int $customer_id + * @param int $commercial_lead_id + * + * @return array + */ + public static function get_addon_package_customer_price($addon_package, $parent_package, $customer_id, $commercial_lead_id) { - foreach ($package_prices as $type => $package_price) { - $customer_package_prices[] = self::_get_package_customer_price( - $package_price, - $cl_commision, - $total_cost, - $is_same_company_as_cl); - } + $parent_total_cost = self::get_package_total_cost($parent_package); + $parent_cl_commision = (100 - Wiaas_Package_Pricing::get_package_pricing_commission($parent_package)) / 100; - return $customer_package_prices; + return self::_get_package_customer_prices( + $addon_package, + $parent_cl_commision, // commercial lead commission of parent package + $parent_total_cost, // total cost of parent package items + $customer_id, + $commercial_lead_id); + } - } + /** + * Calculates customer prices for wiaas option package + * + * @param WC_Product_Bundle $option_package + * @param WC_Product_Bundle $parent_package + * @param int $customer_id + * @param int $commercial_lead_id + * + * @return array + */ + public static function get_option_package_customer_price($option_package, $parent_package, $customer_id, $commercial_lead_id) { - /** - * Calculates customer price for wiaas addon package - * @param $addon_package - * @param $parent_package - * - * @return array - */ - public static function get_addon_package_customer_price($addon_package, $parent_package) { + $parent_total_cost = self::get_package_total_cost($parent_package); + $parent_cl_commision = (100 - Wiaas_Package_Pricing::get_package_pricing_commission($parent_package)) / 100; - $is_same_company_as_cl = self::_is_customer_same_company_as_cl(); - $parent_total_cost = self::get_package_total_cost($parent_package); - $parent_cl_commision = (100 - Wiaas_Package_Pricing::get_package_pricing_commission($parent_package)) / 100; - $addon_package_prices = Wiaas_Package_Pricing::get_package_prices($addon_package); + return self::_get_package_customer_prices( + $option_package, + $parent_cl_commision, // commercial lead commission of parent package + $parent_total_cost, // total cost of parent package items + $customer_id, + $commercial_lead_id); + } - $customer_package_prices = array(); - foreach ($addon_package_prices as $type => $addon_package_price) { - $customer_package_prices[] = self::_get_package_customer_price( - $addon_package_price, - $parent_cl_commision, - $parent_total_cost, - $is_same_company_as_cl); - } - return $customer_package_prices; - } - /** - * Calculates customer price for wiaas option package - * @param $option_package - * @param $parent_package - * - * @return array - */ - public static function get_option_package_customer_price($option_package, $parent_package) { + // PRIVATE SECTION - $is_same_company_as_cl = self::_is_customer_same_company_as_cl(); - $parent_total_cost = self::get_package_total_cost($parent_package); - $parent_cl_commision = (100 - Wiaas_Package_Pricing::get_package_pricing_commission($parent_package)) / 100; - $option_package_prices = Wiaas_Package_Pricing::get_package_prices($option_package); - $customer_package_prices = array(); + /** + * Calculates customer prices for all package payment types + * + * @param WC_Product_Bundle $package + * @param int $cl_commision + * @param int $total_cost + * @param int $customer_id + * @param int $commercial_lead_id + * + * @return array + */ + private static function _get_package_customer_prices($package, $cl_commision, $total_cost, $customer_id, $commercial_lead_id) { + $is_same_company_as_cl = $customer_id === $commercial_lead_id; - foreach ($option_package_prices as $type => $option_package_price) { - $customer_package_prices[] = self::_get_package_customer_price( - $option_package_price, - $parent_cl_commision, - $parent_total_cost, - $is_same_company_as_cl); - } + $package_prices = Wiaas_Package_Pricing::get_package_prices($package); - return $customer_package_prices; - } + $customer_package_prices = array(); - // PRIVATE + foreach ($package_prices as $type => $package_price) { + $cl_package_extras = Wiaas_Package_CL_Pricing::get_extras_for_customer( + $commercial_lead_id, + $package_price['id'], + $package->get_id(), + $customer_id + ); - /** - * Determines if customer and commercial lead are in the same company - * For now this is hardcoded and we have only one CL - * - * TODO: This will be handled in next PR for setting commercial lead prices - * @return bool - */ - private static function _is_customer_same_company_as_cl() { - return false; - } + // commercial lead did not set prices for this payment type so it must not be visible for customer + if (empty($cl_package_extras)) { + continue; + } - /** - * Calculates customer price for wiaas package - * @param $package_price - * @param $cl_commision - * @param $total_cost - * @param $is_same_company_as_cl - * - * @return array - */ - private static function _get_package_customer_price($package_price, $cl_commision, $total_cost, $is_same_company_as_cl) { + $customer_package_prices[] = self::_get_package_customer_price( + $package_price, + $total_cost, + $cl_package_extras, + $cl_commision, + $is_same_company_as_cl); + } - $package_total_margin = wiaas_get_price_margin( - $package_price['minimal_fixed_price'], - $package_price['principal_amount'], - $total_cost); - $cl_margin = $package_total_margin > 0 ? $package_total_margin * $cl_commision : 0; + return $customer_package_prices; + } - $cl_package_prices = array( - 'fixed_extra' => 0, - 'recurrent_extra' => 0, - 'services_extra' => 0 - ); + /** + * Calculates customer price for single package payment type + * + * @param array $package_price + * @param int $total_cost + * @param array $cl_package_extras + * @param int $cl_commision + * @param bool $is_same_company_as_cl + * + * @return array + */ + private static function _get_package_customer_price($package_price, $total_cost, $cl_package_extras, $cl_commision, $is_same_company_as_cl) { + $package_total_margin = wiaas_get_price_margin( + $package_price['minimal_fixed_price'], + $package_price['principal_amount'], + $total_cost); + $cl_margin = $package_total_margin > 0 ? $package_total_margin * $cl_commision : 0; - $interest_rate = self::INTEREST_RATE; + $customer_package_price = array( + 'id' => $package_price['id'], + 'payment_type' => $package_price['payment_type'], + 'max_contract_period' => $package_price['max_contract_period'], + 'package_pay_period' => $package_price['package_pay_period'], + 'period_unit' => $package_price['period_unit'], + 'services_contract_period' => $package_price['services_contract_period'], - $customer_price = array( - 'id' => $package_price['id'], - 'payment_type' => $package_price['payment_type'], - 'max_contract_period' => $package_price['max_contract_period'], - 'package_pay_period' => $package_price['package_pay_period'], - 'period_unit' => $package_price['period_unit'], - 'services_contract_period' => $package_price['services_contract_period'], + 'fixed_extra' => 0, + 'recurrent_extra' => 0, + 'services_extra' => 0 + ); - 'fixed_extra' => 0, - 'recurrent_extra' => 0, - 'services_extra' => 0 - ); + if ($is_same_company_as_cl) { - if ($is_same_company_as_cl) { + if ($package_price['package_pay_period'] > 0) { + $customer_package_price['fixed_extra'] = $package_price['minimal_fixed_price']; + $customer_package_price['recurrent_extra'] = wiaas_get_recurrent_price_mortage( + $package_price['principal_amount'], + $package_price['package_pay_period'], + $cl_margin, + self::INTEREST_RATE); + } else { + $customer_package_price['fixed_extra'] = $package_price['minimal_fixed_price'] - $cl_margin; + $customer_package_price['recurrent_extra'] = 0; + } + $customer_package_price['services_extra'] = $package_price['minimal_services_price']; - if ($package_price['package_pay_period'] > 0) { - $customer_price['fixed_extra'] = $package_price['minimal_fixed_price']; - $customer_price['recurrent_extra'] = wiaas_get_recurrent_price_mortage( - $package_price['principal_amount'], - $package_price['package_pay_period'], - $cl_margin, - $interest_rate); - } else { - $customer_price['fixed_extra'] = $package_price['minimal_fixed_price'] - $cl_margin; - $customer_price['recurrent_extra'] = 0; - } - $customer_price['services_extra'] = $package_price['minimal_services_price']; + } else { - } else { + $customer_package_price['fixed_extra'] = $cl_package_extras['fixed'] + $package_price['minimal_fixed_price']; + $customer_package_price['recurrent_extra'] = $package_price['package_pay_period'] > 0 ? + $cl_package_extras['recurrent'] + wiaas_get_recurrent_price_mortage( + $package_price['principal_amount'], + $package_price['package_pay_period'], + 0, + self::INTEREST_RATE) + : 0; + $customer_package_price['services_extra'] = $cl_package_extras['services'] + $package_price['minimal_services_price']; + } - $customer_price['fixed_extra'] = $cl_package_prices['fixed_extra'] + $package_price['minimal_fixed_price']; - $customer_price['recurrent_extra'] = $package_price['package_pay_period'] > 0 ? - $cl_package_prices['recurrent_extra'] + wiaas_get_recurrent_price_mortage( - $package_price['principal_amount'], - $package_price['package_pay_period'], - 0, - $interest_rate) - : 0; - $customer_price['services_extra'] = $cl_package_prices['services_extra'] + $package_price['minimal_services_price']; - } - - return $customer_price; - } + return $customer_package_price; + } } Wiaas_Pricing::init(); \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-product.php b/backend/app/plugins/wiaas/includes/class-wiaas-product.php index 7197bee..9bf1fc9 100644 --- a/backend/app/plugins/wiaas/includes/class-wiaas-product.php +++ b/backend/app/plugins/wiaas/includes/class-wiaas-product.php @@ -4,7 +4,31 @@ 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'; + + add_filter('woocommerce_register_post_type_product', array(__CLASS__, 'define_product_capabilities')); + } + + /** + * Define capabilities for editing products so we can easily control read/edit/create access for them + * + * @param $args + * + * @return mixed + */ + public static function define_product_capabilities($args) { + + $args['capabilities'] = array( + 'edit_post' => 'edit_product', + 'read_post' => 'read_product', + 'delete_post' => 'delete_product', + 'edit_posts' => 'edit_products', + 'edit_others_posts' => 'edit_others_products', + 'publish_posts' => 'publish_products', + 'read_private_posts' => 'read_private_products', + 'create_posts' => 'create_products', // use `create_products` instead of default `edit_products` + ); + return $args; } } diff --git a/backend/app/plugins/wiaas/includes/class-wiaas-shop.php b/backend/app/plugins/wiaas/includes/class-wiaas-shop.php new file mode 100644 index 0000000..9feb8f2 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/class-wiaas-shop.php @@ -0,0 +1,75 @@ + false, + 'query_var' => true, + 'rewrite' => false, + 'public' => true, + 'capabilities' => array( + 'manage_terms' => 'manage_wiaas_package_price_terms', + 'edit_terms' => 'edit_wiaas_package_price_terms', + 'delete_terms' => 'delete_wiaas_package_price_terms', + 'assign_terms' => 'assign_wiaas_package_price_terms', + ), + ); + + register_taxonomy( '_wiaas_shop_prices', array( 'product' ), $args ); + } + + /** + * Relate pricing search terms to package so customer can retrieve packages with default or + * their own specific prices. + * (ex: Package which will be hidden fro Customer 1 because default price + * is hidden can be visible for Customer 2 because specific prices are set for that customer) + * + * @param int $owner_id + * @param int $package_id + * @param array $cl_extras { + * $extra_price_payment_type => { + * @type bool visible Indicates if payment type is visible to customer + * } + * } + * @param array $old_cl_extras { + * $extra_price_payment_type => { + * @type bool visible Indicates if payment type is visible to customer + * } + * } + */ + public static function update_package_prices_search_terms($owner_id, $package_id, $cl_extras, $old_cl_extras) { + // remove pricing terms for previous prices + if (! empty($old_cl_extras)) { + + $old_visible_price_types = array_keys(wp_list_filter($old_cl_extras, array( 'visible' => true ))); + + $old_terms_names = preg_filter('/^/', '_' . $owner_id . '_', $old_visible_price_types); + + wp_remove_object_terms($package_id, $old_terms_names, '_wiaas_shop_prices'); + } + + // get visible price types set by shop owner (commercial lead) + $visible_price_types = array_keys(wp_list_filter($cl_extras, array('visible' => true))); + + $new_terms_names = preg_filter('/^/', '_' . $owner_id . '_', $visible_price_types); + + // create term for every visible pricing type and link them to package so package can be queried + wp_set_object_terms($package_id, $new_terms_names, '_wiaas_shop_prices'); + } +} + +Wiaas_Shop::init(); diff --git a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-general.php b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-general.php index b8923c8..912de60 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-general.php +++ b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-general.php @@ -113,10 +113,6 @@ function wiaas_db_setup_exclusive_taxonomies() { )); } -function wiaas_db_setup_default_cl() { - wp_insert_term(Wiaas_Pricing::COMMERCIAL_LEAD_NAME, Wiaas_User_Organization::TAXONOMY_NAME); -} - function wiaas_db_setup_customer_capabilities() { $customer_role = get_role('customer'); diff --git a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-roles.php b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-roles.php index e336a43..277a1e0 100644 --- a/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-roles.php +++ b/backend/app/plugins/wiaas/includes/db-updates/wiaas-db-update-roles.php @@ -36,8 +36,7 @@ function wiaas_db_update_create_default_roles() { 'commercial_lead', 'Commercial Lead', array( - 'read', - 'view_admin_dashboard' + 'read' => true, ) ); @@ -45,8 +44,7 @@ function wiaas_db_update_create_default_roles() { 'supplier', 'Supplier', array( - 'read', - 'view_admin_dashboard' + 'read' => true, ) ); @@ -54,7 +52,7 @@ function wiaas_db_update_create_default_roles() { 'user', 'User', array( - 'read' + 'read' => true ) ); @@ -94,12 +92,11 @@ function wiaas_db_update_create_default_roles() { } foreach ( $capabilities as $cap_group ) { - foreach ( $cap_group as $cap ) { - wp_roles()->add_cap( 'administrator', $cap ); - wp_roles()->add_cap( 'commercial_lead', $cap ); - } + foreach ( $cap_group as $cap ) { + wp_roles()->add_cap( 'administrator', $cap ); + wp_roles()->add_cap( 'commercial_lead', $cap ); + } } - } @@ -136,4 +133,44 @@ function wiaas_db_import_aam_role_settings() { 'gravityforms-new-form' => '1', ) ); +} + +function wiaas_db_update_update_commercial_lead_capabilities() { + // add commercial lead specific roles + wp_roles()->add_cap( 'commercial_lead', 'manage_wiaas_cl_products' ); + wp_roles()->add_cap( 'commercial_lead', 'view_admin_dashboard' ); + wp_roles()->add_cap( 'commercial_lead', 'read' ); + wp_roles()->add_cap( 'commercial_lead', 'upload_files' ); + + wp_roles()->add_cap( 'commercial_lead', 'edit_products' ); + wp_roles()->add_cap( 'commercial_lead', 'edit_others_products' ); +} + +function wiaas_db_update_update_supplier_capabilities() { + // add supplier specific roles + wp_roles()->add_cap( 'supplier', 'view_admin_dashboard' ); + wp_roles()->add_cap( 'supplier', 'read' ); +} + +function wiaas_db_update_update_admin_capabilities() { + wp_roles()->add_cap( 'administrator', 'create_products' ); +} + + +function wiaas_create_role_access_groups() { + Groups_Group::create(array( + 'name' => 'admin', + )); + + Groups_Group::create(array( + 'name' => 'commercial_lead', + )); + + Groups_Group::create(array( + 'name' => 'supplier', + )); + + Groups_Group::create(array( + 'name' => 'customer', + )); } \ No newline at end of file diff --git a/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-cl-pricing.php b/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-cl-pricing.php new file mode 100644 index 0000000..a0af916 --- /dev/null +++ b/backend/app/plugins/wiaas/includes/pricing/class-wiaas-package-cl-pricing.php @@ -0,0 +1,114 @@ + $cl_extra) { + unset($cl_extra['type']); + unset($cl_extra['customer']); + + $cl_extras[$extra_type] = $cl_extra; + } + + $old_extras = self::get_extras($owner_id, $package_id); + + // Persist package price extras + update_term_meta( + $owner_id, + '_wiaas_cm_extras_'.$package_id, + $cl_extras); + + do_action('wiaas_package_prices_extras_set', $owner_id, $package_id, $cl_extras, $old_extras); + } + + /** + * Retrieves package catalogue extra prices + * + * @param int $owner_id ID of the shop owner organization who set extra prices + * @param int $package_id + * + * @return array|null + */ + public static function get_extras($owner_id, $package_id) { + $cl_extras = get_term_meta( + $owner_id, + '_wiaas_cm_extras_'.$package_id, + true); + + return is_array($cl_extras) ? $cl_extras : null; + } + + /** + * Retrieve catalogue package extra prices for provided customer + * + * If customer specific prices are set for the package, only those will be retrieved + * otherwise deafult prices exras will be retrieved + * + * @param int $owner_id ID of the shop owner organization who set extra prices + * @param string $pay_type Payment type for the pacakge + * @param int $package_id ID of the package + * @param int $customer_id ID of the customer + * + * @return array|null + */ + public static function get_extras_for_customer($owner_id, $pay_type, $package_id, $customer_id) { + $cl_extras = self::get_extras($owner_id, $package_id); + + if (! empty($cl_extras)) { + // if customer specific prices are set for this package use only them + // else use default prices set for this package + if (self::_customer_specific_prices_exist($cl_extras, $customer_id)) { + $cl_pay_type = $pay_type . '_customer_' . $customer_id; + } else { + $cl_pay_type = $pay_type . '_default'; + } + + $cl_pay_type_extras = $cl_extras[$cl_pay_type]; + + // if commercial lead has default price for this package then use it + if (! empty($cl_pay_type_extras) && $cl_pay_type_extras['visible']) { + + return array( + 'fixed' => floatval($cl_pay_type_extras['fixed']), + 'services' => floatval($cl_pay_type_extras['services']), + 'recurrent' => floatval($cl_pay_type_extras['recurrent']) + ); + } + } + + // there are no prices set for this payment type + return null; + } + + + private static function _customer_specific_prices_exist($cl_extras, $customer_id) { + + $pay_types = array_keys(Wiaas_Package_Pricing::get_available_pay_types()); + + $cl_customer_pay_types = array(); + foreach ($pay_types as $pay_type) { + $cl_customer_pay_types[] = $pay_type.'_customer_'.$customer_id; + } + + foreach ($cl_extras as $cl_pay_type => $data) { + if (in_array($cl_pay_type, $cl_customer_pay_types)) { + return true; + } + } + + return false; + } +} 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 802cee8..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 @@ -167,6 +167,16 @@ class Wiaas_Package_Pricing { 'principal_amount' => floatval($pricing_rule['principal_amount']), 'minimal_services_price' => floatval($pricing_rule['minimal_services_price']), ); + + $minimal_recurrent_price = $prices[$type]['minimal_services_price']; + if ($prices[$type]['principal_amount'] > 0 && $prices[$type]['package_pay_period'] > 0) { + $minimal_recurrent_price += wiaas_PMT( + Wiaas_Pricing::INTEREST_RATE, + $prices[$type]['package_pay_period'], + $prices[$type]['principal_amount']); + } + + $prices[$type]['minimal_recurrent_price'] = round($minimal_recurrent_price); } return $prices; diff --git a/backend/app/plugins/wiaas/includes/user/wiaas-organization-functions.php b/backend/app/plugins/wiaas/includes/user/wiaas-organization-functions.php index 61ed58c..b011408 100644 --- a/backend/app/plugins/wiaas/includes/user/wiaas-organization-functions.php +++ b/backend/app/plugins/wiaas/includes/user/wiaas-organization-functions.php @@ -50,6 +50,7 @@ function wiaas_get_organizations_with_role($role) { 'meta_value' => $role, 'fields' => 'id=>name', 'meta_compare' => 'LIKE', + 'hide_empty' => false )); return is_array($terms) ? $terms : array(); @@ -61,7 +62,7 @@ function wiaas_get_organizations_with_role($role) { * @return array */ function wiaas_get_commercial_leads() { - return wiaas_get_organizations_with_role('shop_manager'); + return wiaas_get_organizations_with_role('commercial_lead'); } /** diff --git a/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-cl-pricing.php b/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-cl-pricing.php new file mode 100644 index 0000000..6dcfcf5 --- /dev/null +++ b/backend/app/plugins/wiaas/tests/unit-tests/pricing/test-wiaas-package-cl-pricing.php @@ -0,0 +1,162 @@ +shop_owner_id = wp_insert_term( + 'Shop owner organization', + Wiaas_User_Organization::TAXONOMY_NAME)['term_id']; + + $this->customer_id = wp_insert_term( + 'Customer Organization', + Wiaas_User_Organization::TAXONOMY_NAME)['term_id']; + + $package = $this->create_new_package(); + + $this->add_products_to_package($package, array( $this->create_new_product())); + + $this->package_id = $package->get_id(); + + $this->cl_extras = array( + 'purchase_default' => array( + 'fixed' => 10, + 'recurrent' => 10, + 'services' => 10, + 'visible' => true + ), + 'purchase_24_default' => array( + 'fixed' => 10, + 'recurrent' => 10, + 'services' => 10, + 'visible' => true + ), + 'managed_36_default' => array( + 'fixed' => 10, + 'recurrent' => 10, + 'services' => 10, + 'visible' => true + ) + ); + } + + /** + * @covers Wiaas_Package_CL_Pricing::set_extras() + */ + function test_packages_extras_set() { + Wiaas_Package_CL_Pricing::set_extras( + $this->shop_owner_id, + $this->package_id, + $this->cl_extras); + + // validate data saved + $cl_extras = get_term_meta( + $this->shop_owner_id, + '_wiaas_cm_extras_' . $this->package_id, + true); + + $this->_validate_default_cl_extras($cl_extras); + } + + /** + * @covers Wiaas_Package_CL_Pricing::get_extras() + */ + function test_package_extras_retrieved() { + update_term_meta( + $this->shop_owner_id, + '_wiaas_cm_extras_' . $this->package_id, + $this->cl_extras); + + $cl_extras = Wiaas_Package_CL_Pricing::get_extras($this->shop_owner_id, $this->package_id); + + $this->_validate_default_cl_extras($cl_extras); + } + + /** + * @covers Wiaas_Package_CL_Pricing::get_extras_for_customer() + */ + function test_default_extras_retrieved_for_customer() { + update_term_meta( + $this->shop_owner_id, + '_wiaas_cm_extras_' . $this->package_id, + $this->cl_extras); + + $pay_types = array_keys(Wiaas_Package_Pricing::get_available_pay_types()); + + foreach ($pay_types as $pay_type) { + $customer_cl_extra = Wiaas_Package_CL_Pricing::get_extras_for_customer( + $this->shop_owner_id, + $pay_type, + $this->package_id, + $this->customer_id); + + $this->assertNotNull($customer_cl_extra); + + $this->assertEquals(10, $customer_cl_extra['fixed']); + $this->assertEquals(10, $customer_cl_extra['recurrent']); + $this->assertEquals(10, $customer_cl_extra['services']); + } + } + + /** + * @covers Wiaas_Package_CL_Pricing::get_extras_for_customer() + */ + function test_customer_specific_extras_retrieved_for_customer() { + // append customer specific extras for purchase payment type + $this->cl_extras['purchase_customer_' . $this->customer_id] = array( + 'fixed' => 100, + 'recurrent' => 100, + 'services' => 100, + 'visible' => true + ); + + // set prices extras + update_term_meta( + $this->shop_owner_id, + '_wiaas_cm_extras_' . $this->package_id, + $this->cl_extras); + + // test that only extras are retrieved for purchase payment type + // and the rest are not retrieved + $pay_types = array_keys(Wiaas_Package_Pricing::get_available_pay_types()); + foreach ($pay_types as $pay_type) { + $customer_cl_extra = Wiaas_Package_CL_Pricing::get_extras_for_customer( + $this->shop_owner_id, + $pay_type, + $this->package_id, + $this->customer_id); + + if ($pay_type === 'purchase') { + + $this->assertNotNull($customer_cl_extra); + + $this->assertEquals(100, $customer_cl_extra['fixed']); + $this->assertEquals(100, $customer_cl_extra['recurrent']); + $this->assertEquals(100, $customer_cl_extra['services']); + } else { + + $this->assertNull($customer_cl_extra); + } + } + } + + + // HELPERS + + private function _validate_default_cl_extras($cl_extras) { + $this->assertNotEmpty($cl_extras); + + $this->assertArrayHasKey('purchase_default', $cl_extras); + $this->assertArrayHasKey('purchase_24_default', $cl_extras); + $this->assertArrayHasKey('managed_36_default', $cl_extras); + + foreach ($cl_extras as $cl_extra) { + $this->assertEquals(10, $cl_extra['fixed']); + $this->assertEquals(10, $cl_extra['recurrent']); + $this->assertEquals(10, $cl_extra['services']); + $this->assertTrue($cl_extra['visible']); + } + } +} \ No newline at end of file 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 83ad6d0..a8d766c 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 @@ -34,6 +34,19 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { $cost_margin = 0; Wiaas_Package_Pricing::set_package_prices($package, $pricing_rules, $commision, $cost_margin); + $customer_id = wp_create_term( + 'Customer', + Wiaas_User_Organization::TAXONOMY_NAME + )['term_id']; + + $commercial_lead_id = wp_create_term( + 'Commercial Lead', + Wiaas_User_Organization::TAXONOMY_NAME + )['term_id']; + + + self::_set_package_default_extras($commercial_lead_id, $package->get_id()); + $expected_prices = array( 'purchase' => array( 'fixed_extra' => 100, @@ -52,7 +65,32 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { ) ); - return array( $package, $expected_prices ); + return array( $package, $expected_prices, $customer_id, $commercial_lead_id ); + } + + private function _set_package_default_extras($commercial_lead_id, $package_id) { + $cl_extras = array( + 'purchase_default' => array( + 'fixed' => 0, + 'recurrent' => 0, + 'services' => 0, + 'visible' => true + ), + 'purchase_24_default' => array( + 'fixed' => 0, + 'recurrent' => 0, + 'services' => 0, + 'visible' => true + ), + 'managed_36_default' => array( + 'fixed' => 0, + 'recurrent' => 0, + 'services' => 0, + 'visible' => true + ) + ); + + Wiaas_Package_CL_Pricing::set_extras($commercial_lead_id, $package_id, $cl_extras); } /** @@ -172,9 +210,12 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { */ function test_get_standard_package_customer_price() { - list( $package, $expected_prices ) = $this->_create_package_to_sell(); + list( $package, $expected_prices, $customer_id, $commercial_lead_id ) = $this->_create_package_to_sell(); - $customer_prices = Wiaas_Pricing::get_standard_package_customer_prices($package); + $customer_prices = Wiaas_Pricing::get_standard_package_customer_prices( + $package, + $customer_id, + $commercial_lead_id); $this->assertCount(3, $customer_prices); @@ -203,7 +244,7 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { * @covers Wiaas_Pricing::get_addon_package_customer_price() */ function test_get_addon_package_customer_price() { - list( $package ) = $this->_create_package_to_sell(); + list( $package, $expected_prices, $customer_id, $commercial_lead_id ) = $this->_create_package_to_sell(); $addon_product = $this->create_new_product(20); $this->add_product_category($addon_product, 'hardware'); @@ -233,6 +274,8 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { $cost_margin = 0; Wiaas_Package_Pricing::set_package_prices($addon_package, $pricing_rules, $commision, $cost_margin); + self::_set_package_default_extras($commercial_lead_id, $addon_package->get_id()); + Wiaas_Package_Addon::set_package_addons($package, array($addon_package->get_id())); $expected_prices = array( @@ -253,7 +296,11 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { ) ); - $customer_prices = Wiaas_Pricing::get_addon_package_customer_price($addon_package, $package); + $customer_prices = Wiaas_Pricing::get_addon_package_customer_price( + $addon_package, + $package, + $customer_id, + $commercial_lead_id); $this->assertCount(3, $customer_prices); @@ -281,7 +328,7 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { * @covers Wiaas_Pricing::get_option_package_customer_price() */ function test_get_option_package_customer_price() { - list( $package ) = $this->_create_package_to_sell(); + list( $package, $customer_id, $commercial_lead_id ) = $this->_create_package_to_sell(); $option_product = $this->create_new_product(20); $this->add_product_category($option_product, 'hardware'); @@ -311,6 +358,8 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { $cost_margin = 0; Wiaas_Package_Pricing::set_package_prices($option_package, $pricing_rules, $commision, $cost_margin); + self::_set_package_default_extras($commercial_lead_id, $option_package->get_id()); + Wiaas_Package_Option_Groups::set_package_option_groups($package, array( 'id' => 'option', 'name' => 'Option', @@ -336,7 +385,11 @@ class Wiaas_Pricing_Test extends Wiaas_Unit_Test_Case { ) ); - $customer_prices = Wiaas_Pricing::get_option_package_customer_price($option_package, $package); + $customer_prices = Wiaas_Pricing::get_option_package_customer_price( + $option_package, + $package, + $customer_id, + $commercial_lead_id); $this->assertCount(3, $customer_prices); diff --git a/backend/app/plugins/wiaas/tests/wiaas-unit-test-factory.php b/backend/app/plugins/wiaas/tests/wiaas-unit-test-factory.php new file mode 100644 index 0000000..4933eae --- /dev/null +++ b/backend/app/plugins/wiaas/tests/wiaas-unit-test-factory.php @@ -0,0 +1,17 @@ + { return dispatch => { dispatch(requestShopPackages()); let searchParam = search ? '?search=' +search : '' - return client.fetch({ - url: `${API_SERVER}/wp-json/wc/v2/products` + searchParam, - // TODO: Add comercialLead parameter after the support for it is added on backend - // method: 'post', - // data: { - // idCommercialLead: (cl && cl.value) || 0, - // search - // } + return client.fetch({ + url: `${API_SERVER}/wp-json/wc/v2/products?cl_id=${cl.idCommercialLead}` + searchParam, }) .then(response => { if (response.data) { @@ -68,23 +62,29 @@ const generateClOptions = (commercialLeads) => { export const fetchShopCommercialLeads = () => { return dispatch => { dispatch(requestShopCommercialLeads()); - // TODO: FetchcomercialLead after the support for it is added on backend - // return client.fetch({url: `${API_SERVER}/coMarket/api/getAllCommercialLeads`}) - // .then(response => { - // if(response.data && response.data.commercialLeads){ - const clOptions = generateClOptions([{ "idCommercialLead": 14, "commercialLeadName": "Coor Service Management", "mail": "rikard@co-ideation.com" }]); - dispatch(recieveShopCommercialLeads(clOptions)); - if (clOptions.length) { - dispatch(selectCommercialLead(clOptions[0])); - dispatch(fetchShopPackages(clOptions[0])); - } + return client.fetch({url: `${API_SERVER}/wp-json/wiaas/commercial-leads` }) + .then(response => { + + if(response.data){ + + const clOptions = generateClOptions(response.data.map(cl => ({ + idCommercialLead: cl.id, + commercialLeadName: cl.name + }))); + + dispatch(recieveShopCommercialLeads(clOptions)); + + if (clOptions.length) { + dispatch(selectCommercialLead(clOptions[0])); + dispatch(fetchShopPackages(clOptions[0])); + } + } + }) + .catch(error => { + client.onError(error, dispatch); + }); } - // }) - // .catch(error => { - // client.onError(error, dispatch); - // }); } -// } export const selectCommercialLead = (cl) => ({ type: SELECT_SHOP_COMMERCIAL_LEAD, diff --git a/frontend/src/containers/coMarket/CoMarketNavContainer.jsx b/frontend/src/containers/coMarket/CoMarketNavContainer.jsx index a1a5716..fc28d5d 100644 --- a/frontend/src/containers/coMarket/CoMarketNavContainer.jsx +++ b/frontend/src/containers/coMarket/CoMarketNavContainer.jsx @@ -16,7 +16,9 @@ class CoMarketNavContainer extends Component { handleSearchChange(event) { this.setState({searchValue: event.target.value}); - this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value)); + if (this.props.selectedCommercialLead) { + this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value)); + } } render() { diff --git a/frontend/src/containers/coMarket/CoMarketPackagesContainer.jsx b/frontend/src/containers/coMarket/CoMarketPackagesContainer.jsx index 2d6d2a1..75e8b49 100644 --- a/frontend/src/containers/coMarket/CoMarketPackagesContainer.jsx +++ b/frontend/src/containers/coMarket/CoMarketPackagesContainer.jsx @@ -8,7 +8,9 @@ import {fetchShopPackages} from '../../actions/coMarket/coMarketPackagesActions' class CoMarketPackagesContainer extends Component { componentDidMount() { - this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead)); + if (this.props.selectedCommercialLead) { + this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead)); + } } render() { diff --git a/frontend/src/containers/coMarket/components/CoMarketCatalogSelect.jsx b/frontend/src/containers/coMarket/components/CoMarketCatalogSelect.jsx index 4b3b93c..c16185a 100644 --- a/frontend/src/containers/coMarket/components/CoMarketCatalogSelect.jsx +++ b/frontend/src/containers/coMarket/components/CoMarketCatalogSelect.jsx @@ -43,7 +43,9 @@ class CoMarketCatalogSelect extends Component { handleSearchChange(event) { this.setState({searchValue: event.target.value}); - this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value)); + if (this.props.selectedCommercialLead) { + this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value)); + } } render() {