27 Commits

Author SHA1 Message Date
Almira Krdzic
5a6f876c69 Merge branch 'master' into package-reference 2018-10-19 21:01:05 +02:00
Nedim Uka
9b5cc3a978 Merge branch 'bundle-cost-summary' into 'master'
Bundle cost summary

See merge request saburly/wiaas/new-wiaas!35
2018-10-19 10:28:24 +00:00
Almira Krdzic
038b622eca Update product properties field 2018-10-19 12:27:25 +02:00
Almira Krdzic
e4ed26de7d add missing comma 2018-10-19 10:27:33 +02:00
Almira Krdzic
094a7bd56c Merge branch 'master' into package-reference 2018-10-19 10:19:45 +02:00
Almira Krdzic
67dc8d7d69 Hide unused tabs and render only edit link for package prices 2018-10-18 20:02:12 +02:00
Almira Krdzic
3ccea1804e Merge branch 'master' into bundle-cost-summary 2018-10-18 19:01:18 +02:00
Almira
315ac70484 Merge branch 'simple-product-details' into 'master'
Added manufacturer and supplyer product numbers

See merge request saburly/wiaas/new-wiaas!30
2018-10-18 17:00:28 +00:00
Nedim Uka
c4cddf8ace Added comment to save post method 2018-10-18 17:30:42 +02:00
Nedim Uka
00e853ae6b Fixed product status issue 2018-10-18 17:28:31 +02:00
Nedim Uka
071c549726 Impleneted search by country, and added mesurment unit 2018-10-18 16:45:26 +02:00
Almira Krdzic
d22ea58568 Import reference ui field 2018-10-18 13:36:45 +02:00
Almira Krdzic
d3c280548b customize column name for reference 2018-10-18 13:28:41 +02:00
Almira Krdzic
1ed7310994 handle package reference 2018-10-18 13:10:55 +02:00
Almira Krdzic
76e9b10235 Merge branch 'master' into bundle-cost-summary 2018-10-18 09:58:15 +02:00
Almira Krdzic
6b0dd0b5a9 handle bundle product prices editor and prices summary 2018-10-18 09:57:44 +02:00
Almira Krdzic
6d65a5f30c handle bundle product prices editor and prices summary 2018-10-18 09:57:38 +02:00
Bilal Catic
c8ed5f7ff8 Merge branch 'resseler-to-customer' into 'master'
Link customers to their respective (commercial leads/ resellers /shops)

See merge request saburly/wiaas/new-wiaas!34
2018-10-17 20:27:03 +00:00
Almira Krdzic
49281f02be remove error logs 2018-10-17 19:40:25 +02:00
Almira Krdzic
b7ab761a25 Handle bundle pricing on separate page 2018-10-17 19:38:41 +02:00
Almira Krdzic
0238f9140e Fixes 2018-10-17 17:45:33 +02:00
Almira Krdzic
4d13ee40bc Add descriptive comments 2018-10-17 14:02:35 +02:00
Almira Krdzic
6c27afabfc Merge branch 'master' into resseler-to-customer 2018-10-17 13:44:15 +02:00
Almira Krdzic
755fc75ae9 Filter linked organizations as customer 2018-10-17 11:31:09 +02:00
Nedim Uka
ecde654ae9 Merge branch 'commercial-lead-prices' into 'master'
Commercial lead prices

See merge request saburly/wiaas/new-wiaas!33
2018-10-17 09:29:54 +00:00
Almira Krdzic
8769606a4b Implement shop search and refactor 2018-10-17 00:36:19 +02:00
Almira Krdzic
afab22a30b reseller to customer 2018-10-16 06:45:28 +02:00
76 changed files with 2779 additions and 664 deletions

View File

@@ -15,3 +15,7 @@
#createuser .acf-taxonomy-field, #your-profile .acf-taxonomy-field { #createuser .acf-taxonomy-field, #your-profile .acf-taxonomy-field {
width: 25em; width: 25em;
} }
.wc-order-preview footer {
display: none;
}

View File

@@ -4,4 +4,8 @@
#menu-posts-product .wp-submenu li:last-child { #menu-posts-product .wp-submenu li:last-child {
display: none; display: none;
}
.woocommerce-BlankState .button {
display: none !important
} }

View File

@@ -30,19 +30,9 @@
} }
#wiaas_package_pricing_rules > .wiaas-pricing-rule { #wiaas_package_pricing_rules > .wiaas-pricing-rule {
border-color:#dfdfdf; border:1px #dfdfdf solid;
border-width:1px; background-color:#fff;
border-style:solid; width: 95%;
-moz-border-radius:3px;
-khtml-border-radius:3px;
-webkit-border-radius:3px;
border-radius:3px;
padding: 0;
border-style:solid;
border-spacing:0;
background-color:#F9F9F9;
margin-bottom: 12px;
margin-left: 12px;
} }
#wiaas_package_pricing_rules > .wiaas-pricing-rule .section { #wiaas_package_pricing_rules > .wiaas-pricing-rule .section {
@@ -133,4 +123,12 @@
#adminmenu #toplevel_page_wiaas-cl-packages div.wp-menu-image::before { #adminmenu #toplevel_page_wiaas-cl-packages div.wp-menu-image::before {
font-family: WooCommerce!important; font-family: WooCommerce!important;
content: '\e006'; content: '\e006';
}
.wiaas-package-error {
color: #a00 !important;
}
table.wp-list-table .column-price {
width: auto !important;
} }

View File

@@ -0,0 +1,150 @@
jQuery(document).ready(function ($) {
$("#wiaas-add-pricing").click(function (event) {
event.preventDefault();
var pay_type = $('#wiaas_pay_types').val();
if (! pay_type) {
return;
}
var set_index = $("#wiaas_package_pricing_rules").data('setindex') + 1;
$("#wiaas_package_pricing_rules").data('setindex', set_index);
var data = {
'pay_type': pay_type,
action: 'create_empty_pricing_rule'
};
$.post(ajaxurl, data, function (response) {
$('#wiaas_package_pricing_rules').append(response);
$(`#wiaas_pay_type_${pay_type}`).prop( 'disabled', true );
$('#wiaas_pay_types').val('0');
});
});
//Remove Pricing Type
$('#wiaas_package_pricing_rules').delegate('.delete_wiaas_pricing_rule', 'click', function (event) {
event.preventDefault();
if (confirm('Are you sure you would like to remove this pay type?')) {
var name = $(this).data('name');
$('#wiaas-pricing-rule-' + name).slideUp().remove();
// append new option to controls
$(`#wiaas_pay_type_${name}`).prop( 'disabled', false );
}
});
$('#wiaas_package_pricing_rules').delegate('.wiaas_minimal_services_price', 'change', function (event) {
event.preventDefault();
var minimal_services_price = parseFloat($(this).val()) || 0;
var principal_amount = 0;
var name = $(this).data('name');
var principal_amount_input = $(`#wiaas_principal_amount_${name}`).first();
if (principal_amount_input) {
principal_amount = parseFloat(principal_amount_input.val() / principal_amount_input.data('period')) || 0;
}
$(`#wiaas_minimal_recurrent_price_${name}`).text((minimal_services_price + principal_amount).toFixed(2));
var services_contract_period = $(this).data('period');
if (services_contract_period > 0) {
var final_services_price = minimal_services_price * services_contract_period;
$(`#wiaas_minimal_services_price_${name}_final`).text(final_services_price.toFixed(2));
}
});
$('#wiaas_package_pricing_rules').delegate('.wiaas_principal_amount', 'change', function (event) {
event.preventDefault();
var value = parseFloat($(this).val());
var period = parseFloat($(this).data('period'));
var interestRate = 0.58;
var principal_amount = wiaasCalculateFinancing(interestRate, period, value);
var minimal_services_price = 0;
var name = $(this).data('name');
var minimal_services_price_input = $(`#wiaas_minimal_services_price_${name}`).first();
if (minimal_services_price_input) {
minimal_services_price = parseFloat(minimal_services_price_input.val()) || 0;
}
$(`#wiaas_minimal_recurrent_price_${name}`).text((minimal_services_price + principal_amount).toFixed(0));
$(`#wiaas_minimal_recurrent_package_price_${name}`).text(principal_amount.toFixed(0));
});
$('#wiaas_package_pricing_editor').delegate('#wiaas_pricing_rules_commision', 'change', function(event) {
event.preventDefault();
var value = parseInt($(this).val());
$('#wiaas_pricing_rules_commission_details').text('Commercial lead: ' + (100 - value) + ' %');
});
$('#wiaas_package_pricing_editor').delegate('#wiaas_pricing_rules_max_cost_margin', 'change', function(event) {
event.preventDefault();
var value = parseFloat($(this).val());
var total = parseFloat($(this).data('total'));
if (value > 0 && value < total) {
$('#wiaas_pricing_rules_max_cost_margin_error').show();
} else {
$('#wiaas_pricing_rules_max_cost_margin_error').hide();
}
});
/**
* Copy of Excel's PMT function.
* Credit: http://stackoverflow.com/questions/2094967/excel-pmt-function-in-js
*
* @param ratePerPeriod The interest rate for the loan.
* @param numberOfPayments The total number of payments for the loan in months.
* @param presentValue The present value, or the total amount that a series of future payments is worth now;
* Also known as the principal.
* @param futureValue The future value, or a cash balance you want to attain after the last payment is made.
* If fv is omitted, it is assumed to be 0 (zero), that is, the future value of a loan is 0.
* @param type Optional, defaults to 0. The number 0 (zero) or 1 and indicates when payments are due.
* 0 = At the end of period
* 1 = At the beginning of the period
* @returns {number}
*/
function wiaasCalculateFinancing(ratePerPeriod, numberOfPayments, presentValue, futureValue = 0, type = 0) {
/*var q = 0;
var c = 0;
const monthlyRatePerPeriod = ratePerPeriod / 12;
if (monthlyRatePerPeriod !== 0.0) {
// Interest rate exists
q = Math.pow(1 + monthlyRatePerPeriod, numberOfPayments);
c = (monthlyRatePerPeriod * (futureValue + (q * presentValue))) / ((-1 + q) * (1 + monthlyRatePerPeriod * (type)));
return c.toFixed(2);
} else if (numberOfPayments !== 0.0) {
// No interest rate, but number of payments exists
return -(futureValue + presentValue) / numberOfPayments;
}
return 0;*/
const rates = {
24 : 4.282,
30 : 3.451,
36 : 2.896,
42 : 2.500,
48 : 2.223,
54 : 2.025,
60 : 1.834
};
const interest = rates[numberOfPayments] || 10;
return presentValue * (interest / 100);
}
});

View File

@@ -0,0 +1,11 @@
jQuery(document).ready(function($) {
if ($('#product-type').val() === 'simple') {
$('#general_product_data').find('.pricing').show();
} else {
$('#general_product_data').find('.pricing').hide();
}
$('#general_product_data').find('.pricing').addClass('hide_if_wiaastemplate hide_if_bundle');
$('#general_product_data').find('.pricing').removeClass('show_if_bundle show_if_wiaastemplate');
});

View File

@@ -0,0 +1,79 @@
<?php
/**
* Class Wiaas_Admin_CL_Customers
*/
class Wiaas_Admin_CL_Customers {
/**
* Displays table list of customers that are linked to commercial lead
*
* Enables commercial lead to update default order type for his shop
*
* Enables commercial lead to update order type for specific shop customer
*
*/
public static function init() {
add_action( 'admin_menu', array( __CLASS__, 'add_customers_page' ), 9 );
}
/**
* Add customer menu page for commercial lead
*/
public static function add_customers_page() {
add_menu_page(
__( 'Customers', 'wiaas' ),
__( 'Customers', 'wiaas' ),
'manage_wiaas_cl_customers',
'wiaas-cl-customers',
array(__CLASS__, 'output_customers'),
'dashicons-groups',
'66.0' );
}
/**
* Render content for customer menu page
*/
public static function output_customers() {
$organization_id = wiaas_get_current_user_organization_id();
// handle default order type update if needed
if (! empty($_POST['wiaas_update_cl_default_order_type_nonce']) &&
! empty($_POST['default_order_type']) &&
wp_verify_nonce(
$_POST['wiaas_update_cl_default_order_type_nonce'],
'wiaas_update_cl_default_order_type')
) {
$default_order_type = sanitize_key($_POST['default_order_type']);
Wiaas_Shop::update_default_order_type($organization_id, $default_order_type);
}
// handle customer order type update if needed
if (! empty($_POST['wiaas_update_cl_customer_order_type_nonce']) &&
! empty($_POST['customer_order_type']) &&
wp_verify_nonce(
$_POST['wiaas_update_cl_customer_order_type_nonce'],
'wiaas_update_cl_customer_order_type')
) {
$customer_id = absint($_POST['customer_order_type']['customer_id']);
$order_type = sanitize_key($_POST['customer_order_type']['order_type']);
Wiaas_Shop::update_shop_customer_order_type(
$organization_id,
$customer_id,
$order_type);
}
$customers = Wiaas_Shop::get_shop_customers($organization_id);
require 'views/html-admin-cl-customers-page.php';
}
}
Wiaas_Admin_CL_Customers::init();

View File

@@ -0,0 +1,126 @@
<?php
/**
* Class Wiaas_Admin_CL_Orders
*/
class Wiaas_Admin_CL_Orders {
/**
* Displays list of orders from commercial lead owned shop
*
* Enables quick preview of each order
*
* This list of orders is achieved with customization of default order list for `shop_order` post
* by using hooks and filters to allow only data that commercial lead should be able to see
*
*/
public static function init() {
add_filter( 'bulk_actions-edit-shop_order', array( __CLASS__, 'remove_bulk_actions_for_list_table_orders' ), 999 );
add_filter('woocommerce_admin_order_preview_actions', array(__CLASS__, 'remove_actions_from_order_preview'));
add_filter('woocommerce_admin_order_preview_line_items', array(__CLASS__, 'filter_order_items_for_order_preview'), 10, 2);
add_filter('manage_shop_order_posts_columns', array(__CLASS__, 'columns_for_list_table_orders'), 999);
add_filter( 'manage_edit-shop_order_sortable_columns', array( __CLASS__, 'define_sortable_columns_for_list_table_orders' ) );
add_action('manage_shop_order_posts_custom_column', array(__CLASS__, 'render_columns_for_list_table_orders'), 999, 2);
}
/**
* Remove all bulk actions for commercial lead
*
* @return array
*/
public static function remove_bulk_actions_for_list_table_orders() {
return array();
}
/**
* Remove actions from shop order preview modal so only data info is visible
*
* @return array
*/
public static function remove_actions_from_order_preview() {
return array();
}
/**
* Show only packages on order preview
*
* @param $order_items
* @param $order
*
* @return array
*/
public static function filter_order_items_for_order_preview($order_items, $order) {
$items = array();
foreach ($order_items as $order_item) {
if (isset($order_item['wiaas_standard_package'])) {
$items[] = $order_item;
}
}
return $items;
}
/**
* Override default table columns so only commercial lead specific columns are visible
*
* @param $columns
*
* @return array
*/
public static function columns_for_list_table_orders($columns) {
$show_columns = array();
$show_columns['cb'] = $columns['cb'];
$show_columns['_wiaas_order_number'] = __( 'Order', 'woocommerce' );
$show_columns['order_date'] = __( 'Date', 'woocommerce' );
$show_columns['order_status'] = __( 'Status', 'woocommerce' );
$show_columns['order_total'] = __( 'Total', 'woocommerce' );
return $show_columns;
}
/** Append commercial lead columns to table sortable columns
*
* @param $sortable_columns
*
* @return mixed
*/
public static function define_sortable_columns_for_list_table_orders($sortable_columns) {
$sortable_columns['_wiaas_order_number'] = 'ID';
return $sortable_columns;
}
/**
* Render commercial lead specific columns
*
* @param $column
* @param $order_id
*/
public static function render_columns_for_list_table_orders($column, $order_id) {
if ($column === '_wiaas_order_number') {
$order = wc_get_order($order_id);
echo '<strong>#' . esc_attr( $order->get_order_number() ) . '</strong>';
if ( $order->get_status() !== 'trash' ) {
echo '<a href="#" class="order-preview" data-order-id="' . absint( $order->get_id() ) . '" title="' . esc_attr( __( 'Preview', 'wiaas' ) ) . '">' . esc_html( __( 'Preview', 'wiaas' ) ) . '</a>';
}
}
}
}
Wiaas_Admin_CL_Orders::init();

View File

@@ -60,8 +60,6 @@ class Wiaas_Admin_CL_Packages {
if ($screen->id === 'admin_page_wiaas-cl-product') { if ($screen->id === 'admin_page_wiaas-cl-product') {
error_log('set parent');
$parent_file = 'edit.php?post_type=product'; $parent_file = 'edit.php?post_type=product';
} }
} }
@@ -150,6 +148,7 @@ class Wiaas_Admin_CL_Packages {
$cl_columns['thumb'] = $columns['thumb']; $cl_columns['thumb'] = $columns['thumb'];
$cl_columns['wiaas_cl_name'] = $columns['name']; $cl_columns['wiaas_cl_name'] = $columns['name'];
$cl_columns['taxonomy-product_tag'] = __( 'Reference', 'wiaas' );
$cl_columns['taxonomy-package_type'] = __('Type', 'wiaas'); $cl_columns['taxonomy-package_type'] = __('Type', 'wiaas');
$cl_columns['taxonomy-package_status'] = __('Status', 'wiaas'); $cl_columns['taxonomy-package_status'] = __('Status', 'wiaas');
$cl_columns['taxonomy-product_country'] = $columns['taxonomy-product_country']; $cl_columns['taxonomy-product_country'] = $columns['taxonomy-product_country'];

View File

@@ -0,0 +1,126 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<style>
select {
width: 300px;
max-width: 100%;
}
</style>
<div class="wrap">
<h1><?php esc_html_e( 'Customers', 'wiaas' ); ?> </h1>
<br class="clear" />
<div id="col-container">
<div id="col-right">
<div class="col-wrap">
<table class="widefat wp-list-table striped" style="width:100%">
<thead>
<tr>
<th scope="col"><?php esc_html_e( 'Name', 'wiaas' ); ?></th>
<th scope="col"><?php esc_html_e( 'Order type', 'wiaas' ); ?></th>
</tr>
</thead>
<tbody>
<?php
foreach ($customers as $customer) {
$name = wiaas_get_organization_name($customer['customer_id']);
?>
<tr>
<td>
<h2><?php esc_html_e($name, 'wiaas') ?></h2>
</td>
<td>
<?php
esc_html_e(
$customer['order_type']=== 'commercial_lead' ? 'Commercial Lead' : 'Reseller',
'wiaas'
)
?>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</div>
<div id="col-left">
<div class="col-wrap">
<div class="inside">
<div class="form-wrap">
<h2><?php esc_html_e('Default order type:', 'wiaas') ?></h2>
<form class="form" action="" method="post">
<input type="hidden" name="page" value="wiaas-cl-customers"/>
<div class="form-field">
<select class="form-control" name="default_order_type">
<option
value="commercial_lead"
<?php selected('commercial_lead', Wiaas_Shop::get_default_order_type($organization_id), true) ?>
>
<?php esc_html_e('Commercial Lead', 'wiaas') ?>
</option>
<option
value="reseller"
<?php selected('reseller', Wiaas_Shop::get_default_order_type($organization_id), true) ?>
>
<?php esc_html_e('Reseller', 'wiaas') ?>
</option>
</select>
</div>
<input class="button button-primary button-large" type="submit" value="Change"/>
<?php wp_nonce_field( 'wiaas_update_cl_default_order_type', 'wiaas_update_cl_default_order_type_nonce' ); ?>
</form>
</div>
<hr style="margin: 30px 0;" />
<div class="form-wrap">
<h2><?php esc_html_e('Update order type for customer', 'wiaas') ?></h2>
<form class="form" action="" method="post">
<div class="form-field">
<label><?php esc_html_e('Customer:', 'wiaas') ?> </label>
<select class="form-control" name="customer_order_type[customer_id]">
<?php
foreach ($customers as $customer) {
$name = wiaas_get_organization_name($customer['customer_id']);
?>
<option
value="<?php esc_html_e($customer['customer_id'], 'wiaas') ?>"
>
<?php esc_html_e($name, 'wiaas') ?>
</option>
<?php
}
?>
</select>
</div>
<div class="form-field">
<label><?php esc_html_e('Order type:', 'wiaas') ?> </label>
<select class="form-control" name="customer_order_type[order_type]">
<option value="commercial_lead">
<?php esc_html_e('Commercial Lead', 'wiaas') ?>
</option>
<option value="reseller">
<?php esc_html_e('Reseller', 'wiaas') ?>
</option>
</select>
</div>
<input class="button button-large" type="submit" value="Update"/>
<?php wp_nonce_field( 'wiaas_update_cl_customer_order_type', 'wiaas_update_cl_customer_order_type_nonce' ); ?>
</form>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -13,14 +13,19 @@ class Wiaas_Admin_CL {
public static function init_admin_cl() { public static function init_admin_cl() {
$user = wp_get_current_user(); $current_user = wp_get_current_user();
$role = $user->roles[0]; $role = $current_user->roles[0];
if ($role === 'commercial_lead') { $is_cl = $role === 'commercial_lead';
if ($is_cl) {
require_once dirname( __FILE__ ) . '/admin-cl/class-wiaas-admin-cl-packages.php'; require_once dirname( __FILE__ ) . '/admin-cl/class-wiaas-admin-cl-packages.php';
require_once dirname( __FILE__ ) . '/admin-cl/class-wiaas-admin-cl-customers.php';
require_once dirname( __FILE__ ) . '/admin-cl/class-wiaas-admin-cl-orders.php';
require_once dirname( __FILE__ ) . '/admin-cl/wiaas-admin-cl-packages-ajax.php'; require_once dirname( __FILE__ ) . '/admin-cl/wiaas-admin-cl-packages-ajax.php';
add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 ); add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 );

View File

@@ -6,7 +6,6 @@ class Wiaas_Admin_Order_Projects {
// Add admin page and subpage since woocommerce orders have custom menu page // Add admin page and subpage since woocommerce orders have custom menu page
// so this will not be automatic // so this will not be automatic
add_filter('admin_menu', array(__CLASS__, 'add_admin_page')); add_filter('admin_menu', array(__CLASS__, 'add_admin_page'));
add_action( 'parent_file', array(__CLASS__, 'highlight_order_projects_parent_menu') );
// Add is available fields to create and edit forms // Add is available fields to create and edit forms
add_action( 'shop_order_project_add_form_fields', array( __CLASS__, 'add_is_available_field' ) ); add_action( 'shop_order_project_add_form_fields', array( __CLASS__, 'add_is_available_field' ) );
@@ -33,19 +32,6 @@ class Wiaas_Admin_Order_Projects {
); );
} }
/**
* Correctly highlight parent menu page when order projects submenu is selected
* @param $parent_file
*
* @return string
*/
public static function highlight_order_projects_parent_menu($parent_file) {
if ( get_current_screen()->taxonomy == 'shop_order_project' ) {
$parent_file = 'woocommerce';
}
return $parent_file;
}
/** /**
* Add is available field to order project creation form * Add is available field to order project creation form
*/ */

View File

@@ -14,8 +14,17 @@ class Wiaas_Admin_Organization {
add_filter('get_role_list', array(__CLASS__, 'get_role_list_for_user'), 10, 2); add_filter('get_role_list', array(__CLASS__, 'get_role_list_for_user'), 10, 2);
// hide woocommerce meta fields form customer user profile
add_filter('woocommerce_customer_meta_fields', array(__CLASS__, 'hide_woocommerce_customer_fields')); add_filter('woocommerce_customer_meta_fields', array(__CLASS__, 'hide_woocommerce_customer_fields'));
// save related customers when organization form data has been saved by acf
add_action('acf/save_post', array(__CLASS__, 'maybe_save_related_customers'), 11);
// load related customers for organization form
add_filter('acf/load_value/name=_wiaas_organization_customers', array(__CLASS__, 'load_related_customer_organizations'), 10, 3);
// retrieve only customer organizations as options to link to commercial lead
add_filter('acf/fields/taxonomy/query/name=_wiaas_organization_customers', array(__CLASS__, 'filter_customer_organizations'));
} }
public static function hide_woocommerce_customer_fields() { public static function hide_woocommerce_customer_fields() {
@@ -26,6 +35,65 @@ class Wiaas_Admin_Organization {
return array(); return array();
} }
/**
* Retrieve only customer organization as options to link customers to commercial lead
*
* @param $args
*
* @return array
*/
public static function filter_customer_organizations($args) {
$args['meta_key'] = '_wiaas_organization_roles';
$args['meta_value'] = 'customer';
$args['meta_compare'] = 'LIKE';
return $args;
}
/**
* Saves related customers if organization new/edit form has been submited
* Customer ids are collected from posted data of linked customers acf field and saved
*
* @param string $id in format `term_{$organization_id}`
*/
public static function maybe_save_related_customers($id) {
if ($_POST['taxonomy'] === Wiaas_User_Organization::TAXONOMY_NAME && ! empty($_POST['acf'])) {
$field = get_field_object('_wiaas_organization_customers', $id);
//get organization id
$id = absint(str_replace('term_', '', $id));
$customer_organization_ids = $_POST['acf'][$field['key']];
$customer_organization_ids = is_array($customer_organization_ids) ?
wp_parse_id_list($customer_organization_ids) :
array();
Wiaas_Shop::set_shop_customers($id, $customer_organization_ids);
}
}
/**
* Loads related customers for linked customers acf field on organization edit form
*
* @param array $value
* @param string $id in format `term_{$organization_id}`
* @param array $field acf field details
*
* @return array
*/
public static function load_related_customer_organizations($value, $id, $field) {
//get organization id
$id = absint(str_replace('term_', '', $id));
$customers = wp_list_pluck(
Wiaas_Shop::get_shop_customers($id),
'customer_id');
return $customers;
}
/** /**
* Render user organization roles as available user roles on user list * Render user organization roles as available user roles on user list
* @param $role_list * @param $role_list

View File

@@ -10,6 +10,42 @@ class Wiaas_Admin_Package {
require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-linked-packages.php'; require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-linked-packages.php';
require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-package-types.php'; require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-package-types.php';
add_action( 'manage_product_posts_columns', array( __CLASS__, 'manage_list_table_products_columns' ), 999, 2 );
add_action( 'woocommerce_product_data_tabs', array( __CLASS__, 'package_data_tabs' ), 999);
}
/**
* Hide default WC_Product data panels.
*
* @param array $tabs
*
* @return mixed
*/
public static function package_data_tabs($tabs) {
$tabs['general']['class'] = array( 'show_if_simple', 'show_if_bundle');
unset($tabs['attribute']);
unset($tabs['variations']);
unset($tabs['advanced']);
unset($tabs['shipping']);
unset($tabs['inventory']);
return $tabs;
}
/**
* Customize list table product columns
*
* @param array $columns
*
* @return array
*/
public static function manage_list_table_products_columns($columns) {
$columns['product_tag'] = __( 'Reference', 'wiaas' );
return $columns;
} }
} }

View File

@@ -0,0 +1,129 @@
<?php
class Wiaas_Admin_Product {
public static function init() {
add_action('acf/save_post', array(__CLASS__, 'wiaas_my_save_post'), 20, 1);
add_action('woocommerce_after_register_post_type', array(__CLASS__, 'wiaas_register_product_status'));
add_filter('woocommerce_register_post_type_product', array(__CLASS__, 'wiaas_modify_product'));
add_action('add_meta_boxes', array(__CLASS__, 'wiaas_maybe_remove_metaboxes'), 999);
add_filter('wp_insert_post_data', array(__CLASS__, 'wiaas_maybe_set_no_country_status'), 999, 2);
add_action('acf/render_field/type=taxonomy', array(__CLASS__, 'wiaas_render_field'), 10, 1);
}
public static function wiaas_modify_product($args) {
$args['supports'] = array('title');
return $args;
}
public static function wiaas_register_product_status() {
register_post_status('_wiaas_no_country', array(
'label' => _x('No Country', 'Product status', 'wiaas'),
'public' => false,
'exclude_from_search' => false,
'show_in_admin_all_list' => false,
'show_in_admin_status_list' => false,
));
}
public static function wiaas_render_field($field) {
if ($field['_name'] === '_wiaas_product_country') {
?>
<div id="submitpost" style="padding: 20px;">
<input style="float:right;" name="save" id="save-post" class="button" type="submit" value="Choose"/>
</div>
<?php
}
}
public static function wiaas_maybe_remove_metaboxes() {
$screen = get_current_screen();
$screen_id = $screen ? $screen->id : '';
if ($screen_id !== 'product') {
return;
}
global $post;
$post_id = $post->ID;
if ($post_id === 0 ||
($post->post_status !== 'publish' && !(Wiaas_Countries::get_package_country(wc_get_product($post_id))))) {
remove_meta_box('woocommerce-product-data', 'product', 'normal');
remove_meta_box('submitdiv', 'product', 'side');
remove_meta_box('slugdiv', 'product', 'normal');
remove_meta_box('wiaas_upload_and_link_document', 'product', 'normal');
remove_meta_box('postexcerpt', 'product', 'normal');
remove_meta_box('template_product_meta_box', 'product', 'normal');
remove_meta_box('postimagediv', 'product', 'normal');
remove_meta_box('woocommerce-product-images', 'product', 'normal');
remove_meta_box('wc-jetpack-product_by_user_role', 'product', 'normal');
remove_meta_box('groups-permissions', 'product', 'side');
remove_meta_box('tagsdiv-product_tag', 'product', 'side');
remove_meta_box('tagsdiv-template_category', 'product', 'side');
remove_meta_box('tagsdiv-supplier', 'product', 'side');
remove_meta_box('postimagediv', 'product', 'side');
remove_meta_box('woocommerce-product-images', 'product', 'side');
remove_meta_box('submitdiv', 'product', 'side');
remove_meta_box('wiaas_upload_and_link_document', 'product', 'side');
remove_meta_box('radio-tagsdiv-product_country', 'product', 'side');
remove_meta_box('tagsdiv-_wiaas_shop_prices', 'product', 'side');
remove_meta_box('tagsdiv-wiaas_units', 'product', 'side');
}
//Always hide product category, it is added wit advanced custom fields plugin for simple product
remove_meta_box('radio-product_catdiv', 'product', 'side');
}
public static function wiaas_maybe_set_no_country_status($data, $postarr) {
if ($postarr['post_type'] === 'product' && (!isset($postarr['ID']) || !$postarr['ID'])) {
$data['post_status'] = '_wiaas_no_country';
}
return $data;
}
/**
* Check for post status and and if there is country available
* Set post status to draft if the country is added
*
* @param $post_id
*/
public static function wiaas_my_save_post($post_id) {
global $post;
$status = get_post_status( $post->ID);
$value = get_field('_wiaas_product_country', $post_id, true);
$type = get_field('_wiaas_product_type', $post_id, true);
error_log($status);
error_log($value);
if (!empty($value) && $status === '_wiaas_no_country' ) {
wp_set_object_terms($post_id, $value, 'product_country', true);
wp_set_object_terms($post_id, $type, 'product_type', true);
wp_update_post(array(
'ID' => $post_id,
'post_status' => 'draft'
));
}
}
}
Wiaas_Admin_Product::init();

View File

@@ -0,0 +1,13 @@
<?php
class Wiaas_Admin_Simple_Product {
public static function init() {
require_once dirname( __FILE__ ) . '/simple-product/class-wiaas-admin-product-additional-info.php';
}
}
Wiaas_Admin_Simple_Product::init();

View File

@@ -11,12 +11,49 @@ class Wiaas_Admin_Package_Pricing {
public static function init() { public static function init() {
add_action( 'woocommerce_product_data_tabs', array( __CLASS__, 'package_data_tabs' ) ); add_action( 'admin_menu', array(__CLASS__, 'add_package_pricing_editor_page') );
add_action( 'woocommerce_product_data_panels', array( __CLASS__, 'package_data_panel' ) );
add_action( 'wp_ajax_create_empty_pricing_rule', array(__CLASS__, 'create_empty_pricing_rule') ); add_action( 'wp_ajax_create_empty_pricing_rule', array(__CLASS__, 'create_empty_pricing_rule') );
add_action( 'woocommerce_process_product_meta', array( __CLASS__, 'process_meta_box' ), 1, 2 ); add_action('woocommerce_product_options_general_product_data', array(__CLASS__, 'render_edit_prices_link'));
add_filter('woocommerce_bundle_price_html', array( __CLASS__, 'get_package_price_html' ), 10, 2);
}
public static function get_package_price_html($price_html, $package) {
$edit_link = admin_url( 'edit.php?post_type=product&page=wiaas-package_price_editor&id=' . absint( $package->get_id() ) );
return '<a class="button button-link" href="' . esc_url($edit_link) .'" target="_blank">Edit price<a>';
}
public static function render_edit_prices_link() {
global $post;
$edit_link = admin_url( 'edit.php?post_type=product&page=wiaas-package_price_editor&id=' . absint( $post->ID ) );
?>
<div class="options_group hide_if_simple hide_if_wiaastemplate">
<p>
<a href="<?php echo esc_url($edit_link) ?>" target="_blank">
<span>Edit prices</span>
</a>
</p>
</div>
<?php
}
public static function add_package_pricing_editor_page() {
add_submenu_page(
'edit.php?post_type=product',
__( 'Edit prices', 'wiaas' ),
null,
'create_products',
'wiaas-package_price_editor',
array(__CLASS__, 'package_pricing_editor')
);
} }
/** /**
@@ -32,48 +69,85 @@ class Wiaas_Admin_Package_Pricing {
die(); die();
} }
/**
* Registers wiaas pricing tab for package data
* @param $tabs
*
* @return array
*/
public static function package_data_tabs($tabs) {
$tabs[ 'bundled_packages_price' ] = array(
'label' => __( 'Pricing', 'wiaas' ),
'target' => 'wiaas_package_price',
'class' => array( 'show_if_bundle', 'bundled_package_tab' ),
'priority' => 50
);
return $tabs;
}
/** /**
* Renderes wiaas pricing tab content for package * Renderes wiaas pricing tab content for package
*/ */
public static function package_data_panel() { public static function package_pricing_editor() {
$plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) );
wp_enqueue_script('admin_package_edit_prices', $plugin_url . '/assets/js/wiaas-admin-package-edit-prices.js');
$package_id = absint($_GET['id']);
$package = wc_get_product( $package_id );
if (empty($package) || $package->get_type() !== 'bundle') {
return;
}
// save prices
if (! empty($_POST['wiaas_save_package_prices_nonce']) &&
wp_verify_nonce($_POST['wiaas_save_package_prices_nonce'], 'wiaas_save_package_prices')) {
self::_save_posted_package_prices($package_id);
}
global $post;
$package = wc_get_product( $post->ID );
$pricing_rules = Wiaas_Package_Pricing::get_package_prices($package); $pricing_rules = Wiaas_Package_Pricing::get_package_prices($package);
$commission = Wiaas_Package_Pricing::get_package_pricing_commission($package); $commission = Wiaas_Package_Pricing::get_package_pricing_commission($package);
$max_cost_margin = Wiaas_Package_Pricing::get_package_max_cost_margin($package); $max_cost_margin = Wiaas_Package_Pricing::get_package_max_cost_margin($package);
include 'views/html-package-pricing.php'; // collect package bundle items pricing info to display
$bundled_items = $package->get_bundled_items();
$bundled_items_per_category = array();
foreach ($bundled_items as $bundled_item) {
$product = $bundled_item->product;
$product_cat = Wiaas_Product_Category::get_category($product);
if ($product_cat === 'hardware' || $product_cat === 'software') {
$product_cat = 'product';
}
$bundled_items_per_category[$product_cat] ?: array( );
$bundled_items_per_category[$product_cat][] = $bundled_item;
}
include 'views/html-package-pricing-page.php';
} }
// PRIVATE HELPERS
/** /**
* Saves posted package pricing rules * Save posted package pricing information
* @param $post_id *
* @param $post * @param int $package_id
*/ */
public function process_meta_box( $post_id, $post ) { private static function _save_posted_package_prices($package_id) {
$commission = wp_unslash($_POST['wiaas_pricing_rules_commision']);
$max_cost_margin = wp_unslash($_POST['wiaas_max_cost_margin']);
$pricing_rules = array();
$posted_pricing_rules = isset($_POST['wiaas_pricing_rules']) ? wp_unslash($_POST['wiaas_pricing_rules']) : array();
foreach ($posted_pricing_rules as $rule_type => $posted_prices) {
$posted_prices = wp_unslash($posted_prices);
$prices = array();
foreach ($posted_prices as $posted_price_type => $posted_price) {
$prices[sanitize_key($posted_price_type)] = wp_unslash($posted_price);
}
$pricing_rules[sanitize_key($rule_type)] = $prices;
}
Wiaas_Package_Pricing::set_package_prices( Wiaas_Package_Pricing::set_package_prices(
wc_get_product( $post_id ), wc_get_product( $package_id ),
$_POST['wiaas_pricing_rules'], $pricing_rules,
$_POST['wiaas_pricing_rules_commision'], $commission,
$_POST['wiaas_max_cost_margin']); $max_cost_margin);
} }
} }

View File

@@ -0,0 +1,277 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<style>
table tr:not(.wiaas-package-price) td:not(:first-child) {
text-align: center;
vertical-align: middle; !important;
}
</style>
<div id="wiaas_package_pricing_editor" class="wrap">
<h1>
<?php
esc_html_e($package->get_title(), 'wiaas');
$country = Wiaas_Countries::get_package_country($package);
if (! empty($country)) {
esc_html_e(' (sold in ' . $country['name'] . ')', 'wiaas');
}
?>
</h1>
<br class="clear" />
<div id="col-container">
<div id="post-body" class="metabox-holder columns-2">
<div id="col-right">
<div class="col-wrap">
<div class="inside">
<table class="widefat">
<tbody>
<?php
$products_total_cost = 0;
$one_time_services_cost = 0;
$recurring_services_cost = 0;
$installation_cost = 0;
foreach ($bundled_items_per_category as $cat => $items) {
?>
<tr style="background: #F5F5F5;">
<td colspan="4">
<strong style="text-transform: uppercase;">
<?php esc_html_e($cat . ' (' . count($items) . ')', 'wiaas') ?>
</strong>
</td>
</tr>
<?php
foreach ($items as $item) {
$product = $item->product;
$product_price = Wiaas_Product_Pricing::get_product_price($product);
$total_cost = Wiaas_Pricing::get_product_total_cost($product);
?>
<tr>
<td>
<span>
<?php esc_html_e($item->get_quantity(), 'wiaas') ?>
x
<?php esc_html_e($product->get_title(), 'wiaas') ?>
</span>
</td>
<td>
<?php
esc_html_e(
$total_cost * $item->get_quantity(),
'wiaas')
?>
</td>
<td>
<?php
esc_html_e(
$total_cost . ' per unit',
'wiaas');
?>
</td>
<td>
<?php
if ($product_price['is_recurring']) {
esc_html_e(
$product_price['price'] . ' / month for ' . $product_price['pay_period'] . ' months',
'wiaas');
} else {
echo '-';
}
?>
</td>
</tr>
<?php
}
?>
<tr class="wiaas-package-price">
<td style="border-top: 1px solid #e5e5e5;"></td>
<td colspan="3" style="border-top: 1px solid #e5e5e5;">
<strong>
<?php
if ($cat === 'product') {
$products_total_cost = wiaas_get_package_hardware_procurement_cost($package) +
wiaas_get_package_software_procurement_cost($package);
esc_html_e('Total: ' . $products_total_cost, 'wiaas');
}
if ($cat === 'service') {
$one_time_services_cost = wiaas_get_package_one_time_services_procurement_cost($package);
$recurring_services_cost = wiaas_get_package_recurring_services_procurement_cost($package);
esc_html_e('One time services: ' . $one_time_services_cost, 'wiaas');
echo '<br>';
esc_html_e('Recurring services: ' . $recurring_services_cost . ' / month ', 'wiaas');
}
if ($cat === 'installation') {
$installation_cost = wiaas_get_package_installation_procurement_cost($package);
esc_html_e('Installation: ' . $installation_cost, 'wiaas');
}
?>
</strong>
</td>
</tr>
<?php
}
?>
</tbody>
<tfoot>
<tr class="wiaas-package-price">
<td>
<h4>TOTAL COST :</h4>
</td>
<td colspan="3">
<strong>Fixed: <?php esc_html_e($products_total_cost + $one_time_services_cost + $installation_cost)?></strong>
<br>
<strong>Recurring: <?php esc_html_e($recurring_services_cost)?> / month</strong>
</td>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
<div id="col-left">
<div class="col-wrap">
<div class="form-wrap">
<h2><?php esc_html_e('Set package prices', 'wiaas') ?></h2>
<form action="" method="post">
<input type="hidden" name="page" value="wiaas-package_price_editor">
<input type="hidden" name="id" value="<?php esc_attr_e($package->get_id(), 'wiaas') ?>">
<div class="form-field">
<label><?php esc_html_e('Max cost margin:', 'wiaas') ?></label>
<input
id="wiaas_pricing_rules_max_cost_margin"
name="wiaas_max_cost_margin"
type="number"
min="0"
value="<?php esc_attr_e($max_cost_margin, 'wiaas') ?>"
data-total="<?php esc_attr_e(Wiaas_Pricing::get_package_total_cost($package), 'wiaas') ?>"
>
<p
id="wiaas_pricing_rules_max_cost_margin_error"
<?php if(Wiaas_Package_Status::get_package_status($package->get_id()) !== Wiaas_Package_Status::INVALID_MARGIN) echo 'style="display: none;"' ?>
class="wiaas-package-error"
>The total costs are greater than the package max margin!</p>
</div>
<div class="form-field">
<label><?php esc_html_e('Commision ( % ):', 'wiaas') ?></label>
<input
id="wiaas_pricing_rules_commision"
name="wiaas_pricing_rules_commision"
type="number"
value="<?php esc_attr_e($commission, 'wiaas') ?>"
min="0" max="100"
>
<p id="wiaas_pricing_rules_commission_details">
<?php esc_html_e('Commercial lead: ' . (100 - $commission) .'%', 'wiaas') ?>
</p>
</div>
<div class="form-field">
<div class="wrap">
<select id="wiaas_pay_types" name="wiaas-pay-type" class="pricing_rule_mode">
<option selected value="0" disabled> Select payment type ...</option>
<?php
$available_pay_types = Wiaas_Package_Pricing::get_available_pay_types();
foreach ($available_pay_types as $name => $pay_type) {
$is_added = ! empty( $pricing_rules[$name])
?>
<option
value="<?php esc_attr_e($name, 'wiaas') ?>"
id="wiaas_pay_type_<?php esc_attr_e($name, 'wiaas') ?>"
<?php disabled($is_added, true, true) ?>
>
<?php esc_html_e( $pay_type['title'], 'wiaas' ); ?>
</option>
<?php
}
?>
</select>
<button
title="<?php _e( 'Add pricing type.', 'wiaas' ); ?>"
id="wiaas-add-pricing"
type="button"
class="button">
<?php _e( 'Add Pricing Type', 'wiaas' ); ?>
</button>
</div>
</div>
<div id="wiaas_package_pricing_rules">
<?php
require 'html-package-pricing-rules-list.php';
?>
</div>
<?php wp_nonce_field( 'wiaas_save_package_prices', 'wiaas_save_package_prices_nonce' ); ?>
<input type="submit" value="Save" class="button button-primary button-large">
</form>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@@ -8,7 +8,7 @@ $available_pay_types = Wiaas_Package_Pricing::get_available_pay_types();
foreach ( $pricing_rules as $name => $pricing_rule ) { foreach ( $pricing_rules as $name => $pricing_rule ) {
$pay_type = $available_pay_types[$name]; $pay_type = $available_pay_types[$name];
?> ?>
<div id="wiaas-pricing-rule-<?php echo $name; ?>" class="wiaas-pricing-rule"> <div id="wiaas-pricing-rule-<?php echo $name; ?>" class="wiaas-pricing-rule form-field">
<div class="section"> <div class="section">
<h4 class="first"><?php echo $pay_type['title']; ?> <h4 class="first"><?php echo $pay_type['title']; ?>
<a href="#" data-name="<?php echo $name; ?>" <a href="#" data-name="<?php echo $name; ?>"

View File

@@ -1,223 +0,0 @@
<?php
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div id="wiaas_package_price" class="panel woocommerce_options_panel">
<script type="text/javascript">
jQuery(document).ready(function ($) {
$("#wiaas-add-pricing").click(function (event) {
event.preventDefault();
var set_index = $("#wiaas_package_pricing_rules").data('setindex') + 1;
$("#wiaas_package_pricing_rules").data('setindex', set_index);
var pay_type = $('#wiaas_pay_type').val();
var data = {
'pay_type': pay_type,
post:<?php echo isset( $_GET['post'] ) ? $_GET['post'] : 0; ?>,
action: 'create_empty_pricing_rule'
};
$.post(ajaxurl, data, function (response) {
$('#wiaas_package_pricing_rules').append(response);
$(`#wiaas_pay_type_${pay_type}`).addClass('wiaas_hidden');
var available_options = $('#wiaas_pay_type option').not('.wiaas_hidden');
if (available_options.length === 0) {
$('#wiaas_package_price_controls').addClass('wiaas_hidden');
} else {
$('#wiaas_pay_type').val(available_options.first().val());
}
});
});
//Remove Pricing Type
$('#wiaas_package_pricing_rules').delegate('.delete_wiaas_pricing_rule', 'click', function (event) {
event.preventDefault();
if (confirm("<?php _e( 'Are you sure you would like to remove this pay type?', 'wiaas' ); ?>")) {
var name = $(this).data('name');
$('#wiaas-pricing-rule-' + name).slideUp().remove();
// append new option to controls
$(`#wiaas_pay_type_${name}`).removeClass('wiaas_hidden');
var available_options = $('#wiaas_pay_type option').not('.wiaas_hidden');
if (available_options.length === 1) {
$('#wiaas_package_price_controls').removeClass('wiaas_hidden');
$('#wiaas_pay_type').val(available_options.first().val());
}
}
});
$('#wiaas_package_pricing_rules').delegate('.wiaas_minimal_services_price', 'change', function (event) {
event.preventDefault();
var minimal_services_price = parseFloat($(this).val()) || 0;
var principal_amount = 0;
var name = $(this).data('name');
var principal_amount_input = $(`#wiaas_principal_amount_${name}`).first();
if (principal_amount_input) {
principal_amount = parseFloat(principal_amount_input.val() / principal_amount_input.data('period')) || 0;
}
$(`#wiaas_minimal_recurrent_price_${name}`).text((minimal_services_price + principal_amount).toFixed(2));
var services_contract_period = $(this).data('period');
if (services_contract_period > 0) {
var final_services_price = minimal_services_price * services_contract_period;
$(`#wiaas_minimal_services_price_${name}_final`).text(final_services_price.toFixed(2));
}
});
$('#wiaas_package_pricing_rules').delegate('.wiaas_principal_amount', 'change', function (event) {
event.preventDefault();
var value = parseFloat($(this).val());
var period = parseFloat($(this).data('period'));
var interestRate = 0.58;
var principal_amount = calculateFinancing(interestRate, period, value);
var minimal_services_price = 0;
var name = $(this).data('name');
var minimal_services_price_input = $(`#wiaas_minimal_services_price_${name}`).first();
if (minimal_services_price_input) {
minimal_services_price = parseFloat(minimal_services_price_input.val()) || 0;
}
$(`#wiaas_minimal_recurrent_price_${name}`).text((minimal_services_price + principal_amount).toFixed(0));
$(`#wiaas_minimal_recurrent_package_price_${name}`).text(principal_amount.toFixed(0));
});
/**
* Copy of Excel's PMT function.
* Credit: http://stackoverflow.com/questions/2094967/excel-pmt-function-in-js
*
* @param ratePerPeriod The interest rate for the loan.
* @param numberOfPayments The total number of payments for the loan in months.
* @param presentValue The present value, or the total amount that a series of future payments is worth now;
* Also known as the principal.
* @param futureValue The future value, or a cash balance you want to attain after the last payment is made.
* If fv is omitted, it is assumed to be 0 (zero), that is, the future value of a loan is 0.
* @param type Optional, defaults to 0. The number 0 (zero) or 1 and indicates when payments are due.
* 0 = At the end of period
* 1 = At the beginning of the period
* @returns {number}
*/
function calculateFinancing(ratePerPeriod, numberOfPayments, presentValue, futureValue = 0, type = 0) {
/*var q = 0;
var c = 0;
const monthlyRatePerPeriod = ratePerPeriod / 12;
if (monthlyRatePerPeriod !== 0.0) {
// Interest rate exists
q = Math.pow(1 + monthlyRatePerPeriod, numberOfPayments);
c = (monthlyRatePerPeriod * (futureValue + (q * presentValue))) / ((-1 + q) * (1 + monthlyRatePerPeriod * (type)));
return c.toFixed(2);
} else if (numberOfPayments !== 0.0) {
// No interest rate, but number of payments exists
return -(futureValue + presentValue) / numberOfPayments;
}
return 0;*/
const rates = {
24 : 4.282,
30 : 3.451,
36 : 2.896,
42 : 2.500,
48 : 2.223,
54 : 2.025,
60 : 1.834
};
const interest = rates[numberOfPayments] || 10;
return presentValue * (interest / 100);
}
});
</script>
<div class="options_group">
<?php
woocommerce_wp_text_input(
array(
'id' => '_wiaas_max_cost_margin',
'name' => 'wiaas_max_cost_margin',
'value' => $max_cost_margin,
'label' => __( 'Max cost margin:', 'wiaas' ),
'type' => 'number',
)
);
?>
</div>
<div class="options_group">
<?php
woocommerce_wp_text_input(
array(
'id' => '_wiaas_price_commision',
'name' => 'wiaas_pricing_rules_commision',
'value' => $commission,
'label' => __( 'Commision (Percent):', 'wiaas' ),
'type' => 'number',
)
);
?>
</div>
<div class="options_group">
<div class="wc-metaboxes-wrapper">
<?php
$has_available_pay_types = false;
$available_pay_types = Wiaas_Package_Pricing::get_available_pay_types();
foreach ($available_pay_types as $name => $pay_type) {
if (!isset($pricing_rule_sets[$name])) {
$has_available_pay_types = true;
break;
}
}
$class = $has_available_pay_types ? '' : 'wiaas_hidden';
?>
<div id="wiaas_package_price_controls" class="toolbar toolbar-top <?php echo $class ?>">
<select id="wiaas_pay_type" name="wiaas-pay-type" class="pricing_rule_mode">
<?php
foreach ($available_pay_types as $name => $pay_type) {
?>
<option
value="<?php echo $name ?>"
id="wiaas_pay_type_<?php echo $name ?>"
class="<?php echo $class ?>"
>
<?php _e( $pay_type['title'], 'wiaas' ); ?>
</option>
<?php
}
?>
</select>
<button
title="<?php _e( 'Add pricing type.', 'wiaas' ); ?>"
id="wiaas-add-pricing"
type="button"
class="button button-primary">
<?php _e( 'Add Pricing Type', 'wiaas' ); ?>
</button>
</div>
<div id="wiaas_package_pricing_rules" class="wc-metaboxes">
<?php
require 'html-package-pricing-rules-list.php';
?>
</div>
</div>
</div>
</div>

View File

@@ -4,29 +4,6 @@ if ( ! defined( 'ABSPATH' ) ) {
} }
?> ?>
<script>
jQuery(document).ready(function($) {
if ($('#product-type').val() === 'simple') {
$('#general_product_data').find('.pricing').show();
} else {
$('#general_product_data').find('.pricing').hide();
}
$('#general_product_data').find('.pricing').attr('class','wiaas_show_if_simple');
$('body').on('woocommerce-product-type-change', function (event, select_val) {
if ('simple' === select_val) {
$('.wiaas_show_if_simple').show();
} else {
$('.wiaas_show_if_simple').hide();
}
});
});
</script>
<?php <?php
woocommerce_wp_checkbox( woocommerce_wp_checkbox(
array( array(

View File

@@ -0,0 +1,91 @@
<?php
class Wiaas_Admin_Product_Additional_Info {
public static function init() {
add_action('woocommerce_product_options_general_product_data', array(__CLASS__, 'display_additional_fields'));
add_action('woocommerce_process_product_meta', array(__CLASS__, 'save_additional_fields'));
add_filter('woocommerce_json_search_found_products', array(__CLASS__, 'filter_product_by_country'));
}
/**
* Add Manufacturer product and Supplier product number fields to
* Simple product general tab
*
*/
public static function display_additional_fields() {
global $post;
$product = wc_get_product( $post->ID );
if ($product->get_type() === 'simple') {
echo '<div class=" product_custom_field ">';
woocommerce_wp_text_input(
array(
'id' => '_manufacturer_product_no',
'label' => __('Manufacturer product number', 'woocommerce'),
'type' => 'text'
)
);
woocommerce_wp_text_input(
array(
'id' => '_supplier_product_no',
'label' => __('Supplier product number', 'woocommerce'),
'type' => 'text'
)
);
echo '</div>';
}
}
public static function filter_product_by_country($search_results) {
$url = wp_get_referer();
if (strpos($url, 'post') === false) {
return $search_results;
}
$post_param = explode("&", parse_url($url, PHP_URL_QUERY))[0];
$post_id = explode("=", $post_param)[1];
$country_id = wp_get_post_terms($post_id, 'product_country', array('fields' => 'ids'))[0];
if (!empty($search_results)) {
$search_result_objects = array_map('wc_get_product', array_keys($search_results));
foreach ($search_result_objects as $result_id => $producta) {
if (Wiaas_Countries::get_product_country_term_id($producta) !== $country_id) {
unset($search_results[$producta->get_id()]);
}
}
}
return $search_results;
}
/**
* Save Manufacturer product and Supplier product number fields to
* Simple product meta data
*
*/
public static function save_additional_fields($post_id) {
$manufacturer_product_no = $_POST['_manufacturer_product_no'];
if (!empty($manufacturer_product_no))
update_post_meta($post_id, '_manufacturer_product_no', esc_attr($manufacturer_product_no));
$supplier_product_no = $_POST['_supplier_product_no'];
if (!empty($supplier_product_no))
update_post_meta($post_id, '_supplier_product_no', esc_attr($supplier_product_no));
}
}
Wiaas_Admin_Product_Additional_Info::init();

View File

@@ -10,7 +10,6 @@ class Wiaas_template {
add_filter('woocommerce_product_data_tabs', array(__CLASS__, 'custom_product_tabs')); add_filter('woocommerce_product_data_tabs', array(__CLASS__, 'custom_product_tabs'));
add_action('woocommerce_product_data_panels', array(__CLASS__, 'wiaastemplate_product_tab_content_all')); add_action('woocommerce_product_data_panels', array(__CLASS__, 'wiaastemplate_product_tab_content_all'));
add_action('woocommerce_admin_process_product_object', array(__CLASS__, 'save_wiaastemplate')); add_action('woocommerce_admin_process_product_object', array(__CLASS__, 'save_wiaastemplate'));
add_filter('woocommerce_product_data_tabs', array(__CLASS__, 'hide_attributes_data_panel'));
add_action('woocommerce_process_product_meta_wiaastemplate', array(__CLASS__, 'save_wiaastemplate')); add_action('woocommerce_process_product_meta_wiaastemplate', array(__CLASS__, 'save_wiaastemplate'));
// Enqueue scripts. // Enqueue scripts.
@@ -198,21 +197,6 @@ class Wiaas_template {
return isset($a['menu_order']) ? 1 : -1; return isset($a['menu_order']) ? 1 : -1;
} }
} }
/**
* Hide default WC_Product data panels.
*/
function hide_attributes_data_panel($tabs) {
$tabs['advanced']['class'][] = 'hide_if_simple_wiaastemplate hide_if_wiaastemplate';
$tabs['shipping']['class'][] = 'hide_if_simple_wiaastemplate hide_if_wiaastemplate';
$tabs['linked_product']['class'][] = 'hide_if_simple_wiaastemplate hide_if_wiaastemplate';
$tabs['attribute']['class'][] = 'hide_if_simple_wiaastemplate hide_if_wiaastemplate';
return $tabs;
}
} }
Wiaas_template::init(); Wiaas_template::init();

View File

@@ -31,12 +31,20 @@ class Wiaas_Cart_API {
'package_id' => array( 'package_id' => array(
'description' => __( 'Wiaas package ID.', 'wiaas' ), 'description' => __( 'Wiaas package ID.', 'wiaas' ),
'type' => 'integer', 'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint',
),
'cl_id' => array(
'description' => __( 'Commercial lead ID.', 'wiaas' ),
'type' => 'integer',
'required' => true,
'sanitize_callback' => 'absint', 'sanitize_callback' => 'absint',
), ),
'price_id' => array( 'price_id' => array(
'description' => __( 'Selected price ID for Wiaas package.', 'wiaas' ), 'description' => __( 'Selected price ID for Wiaas package.', 'wiaas' ),
'type' => 'string', 'type' => 'string',
'enum' => array_keys(Wiaas_Package_Pricing::get_available_pay_types()), 'enum' => array_keys(Wiaas_Package_Pricing::get_available_pay_types()),
'required' => true,
'sanitize_callback' => 'sanitize_key', 'sanitize_callback' => 'sanitize_key',
), ),
'options_ids' => array( 'options_ids' => array(
@@ -210,7 +218,6 @@ class Wiaas_Cart_API {
public static function get_cart_items() { public static function get_cart_items() {
return rest_ensure_response(array( return rest_ensure_response(array(
'items' => Wiaas_Cart::get_cart_packages(), 'items' => Wiaas_Cart::get_cart_packages(),
'raw' => WC()->cart->get_cart_contents(),
)); ));
} }
@@ -225,6 +232,7 @@ class Wiaas_Cart_API {
$success = Wiaas_Cart::add_package_to_cart( $success = Wiaas_Cart::add_package_to_cart(
$request['package_id'], $request['package_id'],
$request['price_id'], $request['price_id'],
$request['cl_id'],
$request['addons_ids'], $request['addons_ids'],
$request['options_ids'] $request['options_ids']
); );

View File

@@ -1,79 +0,0 @@
<?php
class Wiaas_Package_API {
private static $namespace = 'wiaas';
public static function init() {
add_filter('woocommerce_rest_product_object_query', array(__CLASS__, 'filter_packages'), 10, 2);
}
public static function register_routes() {
// TODO: Handle this when assigment of customer to commercial lead is done
register_rest_route( self::$namespace, '/commercial-leads', array(
'methods' => 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();

View File

@@ -1,5 +1,12 @@
<?php <?php
/**
* TODO: Refactor this class so it reflects the fact that customer is an organization
* TODO: Format should be `customer/(?P<organization_id>\d+)/user/(?P<id>\d+)
*
* Class Wiaas_REST_Customer_API
*/
class Wiaas_REST_Customer_API { class Wiaas_REST_Customer_API {
/** /**
* Endpoint namespace. * Endpoint namespace.
@@ -9,13 +16,19 @@ class Wiaas_REST_Customer_API {
private static $namespace = 'wiaas'; private static $namespace = 'wiaas';
public function __construct() { public function __construct() {
include_once dirname( __FILE__ ) . '/../user/class-wiaas-customer.php'; include_once dirname( __FILE__ ) . '/../user/class-wiaas-customer.php';
include_once dirname( __FILE__ ) . '/helper/class-rest-helper-functions.php';
} }
public static function register_routes() { public static function register_routes() {
register_rest_route( self::$namespace, 'customer/(?P<id>\d+)/shops', array(
'methods' => 'GET',
'callback' => array(__CLASS__, 'get_customer_shops'),
'permission_callback' => 'is_user_logged_in'
) );
register_rest_route( self::$namespace, 'customer/(?P<id>\d+)/profile-addresses', array( register_rest_route( self::$namespace, 'customer/(?P<id>\d+)/profile-addresses', array(
'methods' => 'PUT', 'methods' => 'PUT',
'callback' => array(__CLASS__, 'update_customer_profile_addresses'), 'callback' => array(__CLASS__, 'update_customer_profile_addresses'),
@@ -54,6 +67,21 @@ class Wiaas_REST_Customer_API {
} }
public static function get_customer_shops() {
$customer_shops = Wiaas_Customer::get_customer_shops();
$customer_shops = array_map(function($customer_shop) {
return array(
'id' => $customer_shop['owner_id'],
'type' => $customer_shop['order_type'],
'name' => wiaas_get_organization_name($customer_shop['owner_id'])
);
}, $customer_shops);
return rest_ensure_response($customer_shops);
}
public static function update_customer_profile_addresses(WP_REST_Request $request){ public static function update_customer_profile_addresses(WP_REST_Request $request){

View File

@@ -0,0 +1,118 @@
<?php
/**
* Implements wiaas shop based search on top of woocommerce product api
*
* Class Wiaas_WC_Package_API_Integration
*/
class Wiaas_WC_Package_API_Integration {
/**
* Rest base for woocommerce product search
*
* @var string
*/
private static $wc_rest_base = '/wc/v2/products';
public static function init() {
add_filter('woocommerce_rest_product_object_query', array(__CLASS__, 'filter_packages'), 10, 2);
add_filter('rest_dispatch_request', array(__CLASS__, 'validate_package_search_request'), 10, 4);
}
/**
* Force wc api request to send shop id when searching packages
*
* @param $null
* @param $request
* @param $route
* @param $handler
*
* @return null|WP_Error
*/
public static function validate_package_search_request($null, $request, $route, $handler) {
if (strpos($route, self::$wc_rest_base) !== false) {
if (empty($request['shop_id']) || ! absint($request['shop_id'])) {
return new WP_Error(
'missing_shop',
'Shop parameter is missing',
array ( 'status' => 400 )
);
}
}
return null;
}
/**
* 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($args['tax_query']) ){
$args['tax_query'] = array();
}
// Retrieve only packages with available package status
$args['tax_query'][] = array(
'taxonomy' => 'package_status',
'field' => 'name',
'terms' => Wiaas_Package_Status::AVAILABLE
);
/**
* Retrieve packages that satisfy one of two:
*
* 1) Package has at least one visible customer specific price set (for current customer)
* 2) Package has at least one visible default price set and not customer specific prices set (for current customer)
*
* This approach enables us that if package has specific prices set for current customer only those prices
* are taken into account and default ones are ignored.
* Only if package has no specific prices for current customer default prices are taken into account.
*
*/
$shop_id = absint($request['shop_id']);
$customer_id = wiaas_get_current_user_organization_id();
$default_price_search_term = '_' . $shop_id . '_default';
$customer_visible_price_search_term = '_' . $shop_id . '_customer_' . $customer_id . '_visible';
$customer_hidden_price_search_term = '_' . $shop_id . '_customer_' . $customer_id . '_hidden';
$args['tax_query'][] = array(
'relation' => 'OR',
array(
'taxonomy' => '_wiaas_shop_prices',
'terms' => $customer_visible_price_search_term,
'field' => 'slug'
),
array(
array(
'taxonomy' => '_wiaas_shop_prices',
'terms' => $default_price_search_term,
'field' => 'slug'
),
array(
'taxonomy' => '_wiaas_shop_prices',
'terms' => $customer_hidden_price_search_term,
'field' => 'slug',
'operator' => 'NOT IN'
)
)
);
return $args;
}
}
Wiaas_WC_Package_API_Integration::init();

View File

@@ -1,10 +1,22 @@
<?php <?php
/**
* Class Wiaas_Access_Management
*/
class Wiaas_Access_Management { class Wiaas_Access_Management {
/**
* Handles organization and role based access management to wiaas objects (orders, products)
*
* Using Groups Access for achieve this
*
*/
public static function init() { public static function init() {
add_action( 'save_post', array( __CLASS__, 'maybe_handle_product_access' ), 999, 2 ); add_action( 'save_post', array( __CLASS__, 'maybe_handle_product_access' ), 999, 2 );
add_action('woocommerce_new_order', array( __CLASS__, 'assign_order_to_organization' ));
} }
/** /**
@@ -22,28 +34,46 @@ class Wiaas_Access_Management {
$product = wc_get_product($post_id); $product = wc_get_product($post_id);
$admin_access_group = Groups_Group::read_by_name('admin'); $access_group = null;
$access_group_ids = array(); // if product is not bundle or it not completed set it visible only for admin
if ($product->get_type() !== 'bundle' ||
$product->get_status() !== 'publish' ||
empty(Wiaas_Package_Pricing::get_package_prices($product))) {
if ($admin_access_group) { $access_group = Groups_Group::read_by_name('admin');
$access_group_ids[] = $admin_access_group->group_id; } else {
$access_group = Groups_Group::read_by_name('Registered');
} }
// allow commercial lead to see published bundle products if ($access_group) {
$cl_access_group = Groups_Group::read_by_name('commercial_lead'); Groups_Post_Access::update(
array(
if ($product->get_type() === 'bundle' && 'post_id' => $product->get_id(),
$product->get_status() === 'publish' && 'groups_read' => $access_group->group_id
$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 * Assignees order to corresponding user organization when order is created.
) ); *
* @param int $order_id
*/
public static function assign_order_to_organization($order_id) {
// assign order to customer organization
$customer_id = wiaas_get_current_user_organization_id();
Wiaas_User_Organization::assign_post_to_organization($order_id, $customer_id);
$order = wc_get_order($order_id);
// assign order to commercial lead organization
$commercial_lead_id = absint($order->get_meta('_wiaas_commercial_lead_id', true));
if ($commercial_lead_id) {
Wiaas_User_Organization::assign_post_to_organization($order_id, $commercial_lead_id);
}
} }
} }

View File

@@ -12,6 +12,7 @@ class Wiaas_Admin {
require_once dirname(__FILE__) . '/admin/template/class-wiaas-admin-template-selection.php'; require_once dirname(__FILE__) . '/admin/template/class-wiaas-admin-template-selection.php';
require_once dirname(__FILE__) . '/admin/template/class-wiaas-template-products.php'; require_once dirname(__FILE__) . '/admin/template/class-wiaas-template-products.php';
require_once dirname(__FILE__) . '/admin/template/class-wiaas-template-admin-ajax.php'; require_once dirname(__FILE__) . '/admin/template/class-wiaas-template-admin-ajax.php';
require_once dirname(__FILE__) . '/admin/class-wiaas-admin-simple-product.php';
// Admin order projects interface // Admin order projects interface
require_once dirname(__FILE__) . '/admin/class-wiaas-admin-order-projects.php'; require_once dirname(__FILE__) . '/admin/class-wiaas-admin-order-projects.php';
@@ -22,6 +23,8 @@ class Wiaas_Admin {
require_once dirname(__FILE__) . '/admin/class-wiaas-admin-cl.php'; require_once dirname(__FILE__) . '/admin/class-wiaas-admin-cl.php';
require_once dirname(__FILE__) . '/admin/class-wiaas-admin-product.php';
add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 ); add_action( 'admin_enqueue_scripts', array(__CLASS__, 'enqueue_scripts'), 100 );
} }
@@ -30,7 +33,10 @@ class Wiaas_Admin {
$plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) ); $plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) );
wp_enqueue_style( 'wiaas_admin_menu', $plugin_url . '/assets/css/menu.css' ); wp_enqueue_style( 'wiaas_admin_menu', $plugin_url . '/assets/css/menu.css' );
wp_enqueue_style( 'wiaas_admin_packages', $plugin_url . '/assets/css/package.css' );
wp_enqueue_style( 'wiaas_admin_packages', $plugin_url . '/assets/css/wiaas-admin-package.css' );
wp_enqueue_script( 'wiaas_admin_packages', $plugin_url . '/assets/js/wiaas-admin-package.js' );
} }
} }

View File

@@ -43,7 +43,7 @@ class Wiaas_API {
include_once dirname( __FILE__ ) . '/api/class-wiaas-order-projects-api.php'; include_once dirname( __FILE__ ) . '/api/class-wiaas-order-projects-api.php';
include_once dirname( __FILE__ ) . '/api/class-wiaas-package-api.php'; include_once dirname( __FILE__ ) . '/api/class-wiaas-wc- package-api-integration.php';
// API functions // API functions
include_once dirname( __FILE__ ) . '/api/wiaas-api-functions.php'; include_once dirname( __FILE__ ) . '/api/wiaas-api-functions.php';
@@ -58,7 +58,6 @@ class Wiaas_API {
'Wiass_REST_User_API', 'Wiass_REST_User_API',
'Wiaas_REST_Customer_API', 'Wiaas_REST_Customer_API',
'Wiaas_Order_Projects_API', 'Wiaas_Order_Projects_API',
'Wiaas_Package_API'
); );
foreach ( $controllers as $controller ) { foreach ( $controllers as $controller ) {

View File

@@ -26,6 +26,8 @@ class Wiaas_Cart {
add_action( 'woocommerce_before_calculate_totals', array( __CLASS__, 'on_calculate_totals' ), 99, 1); add_action( 'woocommerce_before_calculate_totals', array( __CLASS__, 'on_calculate_totals' ), 99, 1);
add_action( 'woocommerce_cart_loaded_from_session', array( __CLASS__, 'on_calculate_totals' ), 99, 1); add_action( 'woocommerce_cart_loaded_from_session', array( __CLASS__, 'on_calculate_totals' ), 99, 1);
add_action('woocommerce_checkout_create_order', array(__CLASS__, 'add_additional_order_data'), 99);
} }
/** /**
@@ -114,12 +116,13 @@ class Wiaas_Cart {
* *
* @param int $package_id Package ID of selected package * @param int $package_id Package ID of selected package
* @param string $price_id Price ID of selected package payment * @param string $price_id Price ID of selected package payment
* @param int $shop_owner_id Shop owner commercial lead ID
* @param array $addons_ids Array of selected additional packages IDs * @param array $addons_ids Array of selected additional packages IDs
* @param array $options_ids Array of selected option packages IDs * @param array $options_ids Array of selected option packages IDs
* *
* @return bool TRUE if all packages are succesfully added to cart, FALSE otherwise * @return bool TRUE if all packages are succesfully added to cart, FALSE otherwise
*/ */
public static function add_package_to_cart($package_id, $price_id, $addons_ids, $options_ids) { public static function add_package_to_cart($package_id, $price_id, $shop_owner_id, $addons_ids, $options_ids) {
// try adding package to cart // try adding package to cart
try { try {
// Check if package is in cart // Check if package is in cart
@@ -137,19 +140,29 @@ class Wiaas_Cart {
//Check if package is available for adding to cart //Check if package is available for adding to cart
if (Wiaas_Package_Status::get_package_status($package_id) !== Wiaas_Package_Status::AVAILABLE){ if (Wiaas_Package_Status::get_package_status($package_id) !== Wiaas_Package_Status::AVAILABLE){
wc_add_notice('Package cannot be purchased at the moment', 'error'); wc_add_notice('Package cannot be purchased at the moment!', 'error');
return false; return false;
} }
// Retrieve package country // Retrieve package country
$country = Wiaas_Countries::get_package_country($package); $country = Wiaas_Countries::get_package_country($package);
// TODO: Change this so commercial lead is sent via request if (empty($country)) {
wc_add_notice('Package cannot be added do cart!', 'error');
return false;
}
// TODO: Add validation that only packages from the same country can be added to cart at the same time
update_user_meta( get_current_user_id(), '_wiaas_cart_items_country', $country);
// TODO: Add validation that only packages from the same shop can be added to cart at the same time
update_user_meta( get_current_user_id(), '_wiaas_cart_shop_owner_id', $shop_owner_id);
$customer_id = wiaas_get_current_user_organization_id(); $customer_id = wiaas_get_current_user_organization_id();
$commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0];
// Retrieve package price // Retrieve package price
$package_prices = Wiaas_Pricing::get_standard_package_customer_prices($package, $customer_id, $commercial_lead_id); $package_prices = Wiaas_Pricing::get_standard_package_customer_prices($package, $customer_id, $shop_owner_id);
$selected_price_index = array_search($price_id, array_column($package_prices, 'id')); $selected_price_index = array_search($price_id, array_column($package_prices, 'id'));
// Initialize additional cart item data for wiaas packages // Initialize additional cart item data for wiaas packages
@@ -157,7 +170,6 @@ class Wiaas_Cart {
'_wiaas_standard_package' => true, '_wiaas_standard_package' => true,
'_wiaas_addon_items' => array(), '_wiaas_addon_items' => array(),
'_wiaas_option_items' => array(), '_wiaas_option_items' => array(),
'_wiaas_currency' => isset($country) ? $country['currency'] : get_woocommerce_currency(),
'_wiaas_payment' => $package_prices[$selected_price_index] ? $package_prices[$selected_price_index] : null, '_wiaas_payment' => $package_prices[$selected_price_index] ? $package_prices[$selected_price_index] : null,
'_wiaas_documents' => array() '_wiaas_documents' => array()
); );
@@ -170,7 +182,7 @@ class Wiaas_Cart {
} }
// Add selected additional packages and options // Add selected additional packages and options
self::_add_additional_packages_to_cart($cart_item_key, $price_id, $addons_ids, $options_ids); self::_add_additional_packages_to_cart($cart_item_key, $price_id, $shop_owner_id, $addons_ids, $options_ids);
// Trigger calculation of total prices after additional packages are added // Trigger calculation of total prices after additional packages are added
WC()->cart->calculate_totals(); WC()->cart->calculate_totals();
@@ -299,9 +311,6 @@ class Wiaas_Cart {
if (isset($cart_item['_wiaas_standard_package'])) { if (isset($cart_item['_wiaas_standard_package'])) {
$order_item->add_meta_data( '_wiaas_standard_package', $cart_item['_wiaas_standard_package'], true ); $order_item->add_meta_data( '_wiaas_standard_package', $cart_item['_wiaas_standard_package'], true );
} }
if (isset($cart_item['_wiaas_currency'])) {
$order_item->add_meta_data( '_wiaas_currency', $cart_item['_wiaas_currency'], true );
}
// add options metadata // add options metadata
if (isset($cart_item['_wiaas_option_items'])) { if (isset($cart_item['_wiaas_option_items'])) {
@@ -379,11 +388,33 @@ class Wiaas_Cart {
'_wiaas_option_for', '_wiaas_option_for',
'_wiaas_option_group_name', '_wiaas_option_group_name',
'_wiaas_standard_package', '_wiaas_standard_package',
'_wiaas_currency', '_wiaas_documents',
'_wiaas_documents'
) ); ) );
} }
/**
* Sets additional order data form cart after order is successfully created
*
* @param WC_Order $order
*
* @throws WC_Data_Exception
*
*/
public static function add_additional_order_data($order) {
// set order currency
$country = get_user_meta(get_current_user_id(), '_wiaas_cart_items_country', true);
$currency = empty($country) ? get_woocommerce_currency() : $country['currency'];
$order->set_currency($currency);
// set order commercial lead
$shop_owner_id = get_user_meta(get_current_user_id(), '_wiaas_cart_shop_owner_id', true);
$shop_owner_id = absint($shop_owner_id);
$order->add_meta_data('_wiaas_commercial_lead_id', $shop_owner_id);
}
/** /**
* Calculate total cost for cart item * Calculate total cost for cart item
* *
@@ -451,6 +482,9 @@ class Wiaas_Cart {
public static function get_cart_packages() { public static function get_cart_packages() {
$items = WC()->cart->get_cart_contents(); $items = WC()->cart->get_cart_contents();
$shop_owner_id = get_user_meta(get_current_user_id(), '_wiaas_cart_shop_owner_id', true);
$shop_owner_id = absint($shop_owner_id);
$package_items = array(); $package_items = array();
foreach ($items as $key => $item) { foreach ($items as $key => $item) {
@@ -500,8 +534,8 @@ class Wiaas_Cart {
'package_name' => $package->get_title(), 'package_name' => $package->get_title(),
'quantity' => $item['quantity'], 'quantity' => $item['quantity'],
'commercial_lead_id' => 14, 'commercial_lead_id' => $shop_owner_id,
'commercial_lead' => 'Coor Service Management', 'commercial_lead' => wiaas_get_organization_name($shop_owner_id),
'country' => Wiaas_Countries::get_package_country($package), 'country' => Wiaas_Countries::get_package_country($package),
'are_additional_available' => true, 'are_additional_available' => true,
@@ -636,21 +670,20 @@ class Wiaas_Cart {
* *
* @param string $package_cart_item_key * @param string $package_cart_item_key
* @param int $price_id * @param int $price_id
* @param int $shop_owner_id
* @param array $addons_ids * @param array $addons_ids
* @param array $options_ids * @param array $options_ids
* *
* @throws Exception if any of the addons or options cannot be added to cart * @throws Exception if any of the addons or options cannot be added to cart
*/ */
private static function _add_additional_packages_to_cart($package_cart_item_key, $price_id, $addons_ids, $options_ids) { private static function _add_additional_packages_to_cart($package_cart_item_key, $price_id, $shop_owner_id, $addons_ids, $options_ids) {
$parent_item = WC()->cart->get_cart_item($package_cart_item_key); $parent_item = WC()->cart->get_cart_item($package_cart_item_key);
$addon_items_keys = array(); $addon_items_keys = array();
$option_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(); $customer_id = wiaas_get_current_user_organization_id();
$commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0];
// Try adding package addons to cart // Try adding package addons to cart
foreach ($addons_ids as $addon_id) { foreach ($addons_ids as $addon_id) {
@@ -665,7 +698,7 @@ class Wiaas_Cart {
$addon_package, $addon_package,
$parent_item['data'], $parent_item['data'],
$customer_id, $customer_id,
$commercial_lead_id $shop_owner_id
); );
$selected_price_index = array_search($price_id, array_column($package_prices, 'id')); $selected_price_index = array_search($price_id, array_column($package_prices, 'id'));
@@ -702,7 +735,7 @@ class Wiaas_Cart {
$option_package, $option_package,
$parent_item['data'], $parent_item['data'],
$customer_id, $customer_id,
$commercial_lead_id); $shop_owner_id);
$selected_price_index = array_search($price_id, array_column($package_prices, 'id')); $selected_price_index = array_search($price_id, array_column($package_prices, 'id'));
// Retrieve option package group name // Retrieve option package group name

View File

@@ -83,14 +83,6 @@ class Wiaas_Checkout {
* @param array $data * @param array $data
*/ */
private static function _add_wiaas_checkout_data($order, $data) { private static function _add_wiaas_checkout_data($order, $data) {
// save currency
$line_items = $order->get_items();
foreach ($line_items as $line_item) {
if (isset($line_item['wiaas_currency'])) {
$order->set_currency($line_item['wiaas_currency']);
break;
}
}
// save additional wiaas order info // save additional wiaas order info
Wiaas_Order::set_order_vat($order->get_id(), $data['vat']); Wiaas_Order::set_order_vat($order->get_id(), $data['vat']);
@@ -102,6 +94,7 @@ class Wiaas_Checkout {
if (isset($data['project_id'])) { if (isset($data['project_id'])) {
Wiaas_Order_Project::set_project_for_order($order->get_id(), $data['project_id']); Wiaas_Order_Project::set_project_for_order($order->get_id(), $data['project_id']);
} }
} }
} }

View File

@@ -114,12 +114,25 @@ class Wiaas_Countries {
* *
* @return array|null * @return array|null
*/ */
public static function get_product_country($product) { public static function get_product_country($product) {
$product_country = get_the_terms($product->get_id(), 'product_country'); $product_country = get_the_terms($product->get_id(), 'product_country');
return is_array($product_country) && isset($product_country[0]) ? return is_array($product_country) && isset($product_country[0]) ?
self::$available_countries[$product_country[0]->name] : self::$available_countries[$product_country[0]->name] :
null; null;
} }
/**
* Retrieves country term id from db for provided product
* @param $product
*
* @return int|null
*/
public static function get_product_country_term_id($product) {
$product_country = get_the_terms($product->get_id(), 'product_country');
return is_array($product_country) && isset($product_country[0]) ?
$product_country[0]->term_id :
null;
}
} }
Wiaas_Countries::init(); Wiaas_Countries::init();

View File

@@ -13,14 +13,18 @@ class Wiaas_DB_Update {
'20180826153509' => 'wiaas_create_broker_access_group', '20180826153509' => 'wiaas_create_broker_access_group',
'20180911101010' => 'wiaas_db_setup_exclusive_taxonomies', '20180911101010' => 'wiaas_db_setup_exclusive_taxonomies',
'20181003164100' => 'wiaas_db_setup_customer_capabilities', '20181003164100' => 'wiaas_db_setup_customer_capabilities',
'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', '201810171645700' => 'wiaas_db_update_create_default_roles',
'201810171745700' => 'wiaas_db_import_aam_role_settings', '201810171745700' => 'wiaas_db_import_aam_role_settings',
'201810173045700' => 'wiaas_db_update_update_commercial_lead_capabilities', '201810180145700' => 'wiaas_db_update_update_supplier_capabilities',
'201810173145700' => 'wiaas_db_update_update_supplier_capabilities', '201810180245700' => 'wiaas_db_update_update_admin_capabilities',
'201810173245700' => 'wiaas_db_update_update_admin_capabilities', '201810180345700' => 'wiaas_create_role_access_groups',
'201810173345700' => 'wiaas_create_role_access_groups' '201810180444700' => 'wiaas_db_setup_create_customer_commercial_lead_table',
'201810180544702' => 'wiaas_db_update_update_commercial_lead_capabilities',
'201810180644703' => 'wiaas_db_update_add_organization_info_ui_fields',
'201910190145700' => 'wiaas_db_update_add_general_ui_fields',
'201910190146700' => 'wiaas_db_update_add_product_properties_ui_fields',
'201810190644704' => 'wiaas_db_update_add_reference_ui_field'
); );
public static function execute() { public static function execute() {

View File

@@ -0,0 +1,11 @@
<?php
class Wiaas_DB {
public static function init() {
require_once dirname( __FILE__ ) . '/db/class-wiaas-shop-db.php';
}
}
Wiaas_DB::init();

View File

@@ -19,7 +19,7 @@ class Wiaas_Order {
require_once dirname( __FILE__ ) . '/order/class-wiaas-order-project.php'; require_once dirname( __FILE__ ) . '/order/class-wiaas-order-project.php';
add_action('woocommerce_new_order', array( __CLASS__, 'assign_order_to_organization' )); add_filter('woocommerce_register_post_type_shop_order', array(__CLASS__, 'manage_order_settings'));
add_filter('woocommerce_rest_check_permissions', array( __CLASS__, 'check_order_access'), 10, 4); add_filter('woocommerce_rest_check_permissions', array( __CLASS__, 'check_order_access'), 10, 4);
@@ -30,6 +30,35 @@ class Wiaas_Order {
add_filter('woocommerce_new_order_note_data', array( __CLASS__, 'update_new_order_comment_date'), 10, 3); add_filter('woocommerce_new_order_note_data', array( __CLASS__, 'update_new_order_comment_date'), 10, 3);
} }
/**
* Update `shop_order` post type settings before creation to enable better order management for wiaas
*
* @param array $args
*
* @return array
*/
public static function manage_order_settings($args) {
// show orders in backend menu
$args['show_in_menu'] = true;
//set icon
$args['menu_icon'] = 'dashicons-cart';
// set capabilities
$args['capabilities'] = array(
'edit_post' => 'edit_shop_order',
'read_post' => 'read_shop_order',
'delete_post' => 'delete_shop_order',
'edit_posts' => 'edit_shop_orders',
'edit_others_posts' => 'edit_others_shop_orders',
'publish_posts' => 'publish_shop_orders',
'read_private_posts' => 'read_private_shop_orders',
'create_posts' => 'create_shop_orders', // use `create_shop_orders` instead of `edit_shop_orders`
);
return $args;
}
public static function update_new_order_comment_date($comment_data, $order_data) { public static function update_new_order_comment_date($comment_data, $order_data) {
$user = wp_get_current_user(); $user = wp_get_current_user();
@@ -39,16 +68,6 @@ class Wiaas_Order {
return $comment_data; return $comment_data;
} }
/**
* Assignees order to corresponding user organization when order is created.
*
* @param $order_id
*/
public static function assign_order_to_organization($order_id) {
$user = wp_get_current_user();
Wiaas_User_Organization::assign_post_to_user_organization($order_id, $user->ID);
}
/** /**
* Checks if current user has access to requested order/{orderId} via woocommerce REST API. * Checks if current user has access to requested order/{orderId} via woocommerce REST API.
* Endpoint `/orders` is filtered correctly by groups, but endpoint `/orders/{orderId}` will return order even if * Endpoint `/orders` is filtered correctly by groups, but endpoint `/orders/{orderId}` will return order even if

View File

@@ -32,6 +32,9 @@ class Wiaas_Package {
$data = self::_append_country_info($data, $package, $request); $data = self::_append_country_info($data, $package, $request);
// append package reference field
$data['reference'] = ! empty($data['tags']) ? $data['tags'][0]['name'] : '';
if (isset($request['id'])) { if (isset($request['id'])) {
$data = self::_append_package_prices($data, $package, $request); $data = self::_append_package_prices($data, $package, $request);
@@ -93,9 +96,8 @@ class Wiaas_Package {
* @return array * @return array
*/ */
private static function _append_additional_packages($data, $package, $request) { 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(); $customer_id = wiaas_get_current_user_organization_id();
$commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0]; $commercial_lead_id = absint($request['shop_id']);
$data['additional_packages'] = array(); $data['additional_packages'] = array();
$addons = Wiaas_Package_Addon::get_package_addons($package); $addons = Wiaas_Package_Addon::get_package_addons($package);
@@ -142,9 +144,8 @@ class Wiaas_Package {
* @return array * @return array
*/ */
private static function _append_package_prices($data, $package, $request) { private static function _append_package_prices($data, $package, $request) {
// TODO: Change this so commercial lead is sent via request
$customer_id = wiaas_get_current_user_organization_id(); $customer_id = wiaas_get_current_user_organization_id();
$commercial_lead_id = array_keys(wiaas_get_commercial_leads())[0]; $commercial_lead_id = absint($request['shop_id']);
$data['prices'] = Wiaas_Pricing::get_standard_package_customer_prices($package, $customer_id, $commercial_lead_id); $data['prices'] = Wiaas_Pricing::get_standard_package_customer_prices($package, $customer_id, $commercial_lead_id);

View File

@@ -6,17 +6,21 @@ class Wiaas_Product {
require_once dirname( __FILE__ ) . '/product/class-wiaas-product-category.php'; 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')); add_filter('woocommerce_register_post_type_product', array(__CLASS__, 'manage_product_settings'));
add_filter('woocommerce_taxonomy_args_product_tag', array(__CLASS__, 'manage_tags_as_references'));
} }
/** /**
* Define capabilities for editing products so we can easily control read/edit/create access for them * Update product type settins before it is created:
* - Define capabilities for editing products so we can easily control read/edit/create access for them
* - Declare fields supported by product
* *
* @param $args * @param $args
* *
* @return mixed * @return array
*/ */
public static function define_product_capabilities($args) { public static function manage_product_settings($args) {
$args['capabilities'] = array( $args['capabilities'] = array(
'edit_post' => 'edit_product', 'edit_post' => 'edit_product',
@@ -28,6 +32,42 @@ class Wiaas_Product {
'read_private_posts' => 'read_private_products', 'read_private_posts' => 'read_private_products',
'create_posts' => 'create_products', // use `create_products` instead of default `edit_products` 'create_posts' => 'create_products', // use `create_products` instead of default `edit_products`
); );
$args['supports'] = array( 'title', 'thumbnail' );
return $args;
}
/**
* Hide default metabox for product tags
*
* @param $args
*
* @return array
*/
public static function manage_tags_as_references($args) {
// hide metabox
$args['meta_box_cb'] = false;
// update labels
$args['labels'] = array(
'name' => __( 'Product references', 'wiaas' ),
'singular_name' => __( 'Reference', 'wiaas' ),
'menu_name' => _x( 'References', 'Admin menu name', 'wiaas' ),
'search_items' => __( 'Search references', 'wiaas' ),
'all_items' => __( 'All references', 'wiaas' ),
'edit_item' => __( 'Edit reference', 'wiaas' ),
'update_item' => __( 'Update reference', 'wiaas' ),
'add_new_item' => __( 'Add new reference', 'wiaas' ),
'new_item_name' => __( 'New reference name', 'wiaas' ),
'popular_items' => __( 'Popular references', 'wiaas' ),
'separate_items_with_commas' => __( 'Separate references with commas', 'wiaas' ),
'add_or_remove_items' => __( 'Add or remove references', 'wiaas' ),
'choose_from_most_used' => __( 'Choose from the most used references', 'wiaas' ),
'not_found' => __( 'No references found', 'wiaas' ),
);
return $args; return $args;
} }
} }

View File

@@ -1,5 +1,13 @@
<?php <?php
/**
* Implements logic for multiple shops existing in one marketplace
*
* Every shop has its owner (organization that is commercial lead) and multiple customers (organizations)
* assigned to it.
*
* Class Wiaas_Shop
*/
class Wiaas_Shop { class Wiaas_Shop {
public static function init() { public static function init() {
@@ -10,6 +18,86 @@ class Wiaas_Shop {
// update prices search terms for package after prices extras have been updated // update prices search terms for package after prices extras have been updated
add_action('wiaas_package_prices_extras_set', array(__CLASS__, 'update_package_prices_search_terms'), 10, 4); add_action('wiaas_package_prices_extras_set', array(__CLASS__, 'update_package_prices_search_terms'), 10, 4);
// create new shop if organization was assigned commercial lead role
// or remove shop if commercial lead role was removed for organization
add_action('wiaas_organization_roles_updated', array(__CLASS__, 'maybe_manage_shop_for_commercial_lead'), 10, 2);
}
public static function get_shop_customers($owner_id) {
return Wiaas_Shop_DB::get_shop_customers($owner_id);
}
/**
* Link customers to shop (this will enable them to search and order packages from this shop)
*
* @param int $owner_id
* @param array $customer_ids
*/
public static function set_shop_customers($owner_id, $customer_ids) {
$current_customer_ids = wp_list_pluck(
Wiaas_Shop_DB::get_shop_customers($owner_id),
'customer_id');
// delete removed customers
$removed_customer_ids = array_diff($current_customer_ids, $customer_ids);
Wiaas_Shop_DB::remove_shop_customers($owner_id, $removed_customer_ids);
// save added customers
$added_customer_ids = array_diff($customer_ids, $current_customer_ids);
Wiaas_Shop_DB::add_shop_customers($owner_id, $added_customer_ids);
}
/**
* Retrieve default order type for shop
*
* @param int $owner_id
*
* @return string
*/
public static function get_default_order_type($owner_id) {
$order_type = get_term_meta(
$owner_id,
'_wiaas_shop_default_order_type',
true);
return empty($order_type) ? 'commercial_lead' : $order_type;
}
/**
* Update default order type for shop
*
* @param int $owner_id
* @param string $order_type
*/
public static function update_default_order_type($owner_id, $order_type) {
if (in_array($order_type, array('commercial_lead', 'reseller'))) {
update_term_meta($owner_id, '_wiaas_shop_default_order_type', $order_type);
}
}
public static function update_shop_customer_order_type($owner_id, $customer_id, $order_type) {
Wiaas_Shop_DB::update_shop_customer_order_type(
$owner_id,
$customer_id,
$order_type);
}
/**
* Creates shop for new shop owner (organization with commercial lead role) or
* deletes existing shop if that role has been removed
*
* @param int $owner_id
* @param array $roles
*/
public static function maybe_manage_shop_for_commercial_lead($owner_id, $roles) {
$is_commercial_lead = in_array('commercial_lead', $roles);
$is_commercial_lead ?
self::_maybe_create_shop($owner_id) :
self::_maybe_remove_shop($owner_id);
} }
/** /**
@@ -20,7 +108,7 @@ class Wiaas_Shop {
'hierarchical' => false, 'hierarchical' => false,
'query_var' => true, 'query_var' => true,
'rewrite' => false, 'rewrite' => false,
'public' => true, 'public' => false,
'capabilities' => array( 'capabilities' => array(
'manage_terms' => 'manage_wiaas_package_price_terms', 'manage_terms' => 'manage_wiaas_package_price_terms',
'edit_terms' => 'edit_wiaas_package_price_terms', 'edit_terms' => 'edit_wiaas_package_price_terms',
@@ -55,20 +143,109 @@ class Wiaas_Shop {
// remove pricing terms for previous prices // remove pricing terms for previous prices
if (! empty($old_cl_extras)) { if (! empty($old_cl_extras)) {
$old_visible_price_types = array_keys(wp_list_filter($old_cl_extras, array( 'visible' => true ))); $old_terms = self::_get_search_terms_from_cl_extras($owner_id, $old_cl_extras);
$old_terms_names = preg_filter('/^/', '_' . $owner_id . '_', $old_visible_price_types); wp_remove_object_terms($package_id, $old_terms, '_wiaas_shop_prices');
wp_remove_object_terms($package_id, $old_terms_names, '_wiaas_shop_prices');
} }
// get visible price types set by shop owner (commercial lead) $new_terms = self::_get_search_terms_from_cl_extras($owner_id, $cl_extras);
$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 // 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'); wp_add_object_terms($package_id, $new_terms, '_wiaas_shop_prices');
}
// PRIVATE
/**
* Each shop will be registered as product attribute.
* This will persist shops information into database.
* Also every attribute has taxonomy associated with it which will enable us to have multiple
* catalogues in one shop
*
* @param int $owner_id
*/
private static function _maybe_create_shop($owner_id) {
$shop_name = 'wiaas_shop_' . $owner_id;
$attribute_id = wc_attribute_taxonomy_id_by_name($shop_name);
if ($attribute_id === 0) {
// create shop attribute
wc_create_attribute(array( 'slug' => $shop_name, 'name' => 'Shop' ));
$taxonomy_name = wc_attribute_taxonomy_name($shop_name);
// since attribute taxonomies are registered once on load
// we will register new attribute taxonomy here so default catalogue can be added
register_taxonomy($taxonomy_name, array('product'));
// add default catalogue option to shop
wp_insert_term( 'Default Catalogue', $taxonomy_name);
}
}
/**
* Deleted associated attribute for shop. This will effectively remove shop and all of its potential catalogues
*
* @param int $owner_id
*/
private static function _maybe_remove_shop($owner_id) {
// get corresponding attribute for shop
$attribute_id = wc_attribute_taxonomy_id_by_name('wiaas_shop_' . $owner_id);
// if shop attribute exists then remove it
if ($attribute_id > 0) {
wc_delete_attribute($attribute_id);
}
}
/**
* Generate search terms from cl extras
*
* For default prices search term
* `_{owner_id}_default` will be generated if all set prices are visible
*
* For every customer entry search term
* `_{owner_id}_customer_{customer_id}_visible` will be generated if any of the prices is visible or
* `_{owner_id}_customer_{customer_id}_hidden` if all prices are hidden`
*
* @param int $owner_id
* @param array $cl_extras
*
* @return array
*/
private static function _get_search_terms_from_cl_extras($owner_id, $cl_extras) {
// determine if extras are visible grouped by customer and default settings
$cl_extras_per_customer = array();
$cl_extra_default = false;
foreach ($cl_extras as $cl_extra_type => $cl_extra) {
// is default
if (strpos($cl_extra_type, '_default') !== false) {
// determine if default cl extra is visible
$cl_extra_default = $cl_extra_default || $cl_extra['visible'];
}
// is customer specific
if (strpos($cl_extra_type, '_customer_') !== false) {
$customer_id = absint(explode('_customer_', $cl_extra_type)[1]);
// determine if customer cl extra is visible
$cl_extras_per_customer[$customer_id] = $cl_extras_per_customer[$customer_id] || $cl_extra['visible'];
}
}
$terms = array();
if ($cl_extra_default) {
$terms[] = '_' . $owner_id . '_default';
}
foreach ($cl_extras_per_customer as $customer_id => $visible) {
$terms[] = '_' . $owner_id . '_customer_' . $customer_id . '_' .
($visible ? 'visible' : 'hidden');
}
return $terms;
} }
} }

View File

@@ -0,0 +1,86 @@
[
{
"key": "group_5bbf694106e34",
"title": "General",
"fields": [
{
"key": "field_5bc0965a35406",
"label": "Type",
"name": "_wiaas_product_type",
"type": "select",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"choices": {
"simple": "Simple",
"bundle": "Bundle",
"wiaastemplate": "Template"
},
"default_value": [],
"allow_null": 0,
"multiple": 0,
"ui": 1,
"ajax": 0,
"return_format": "value",
"placeholder": ""
},
{
"key": "field_5bbf899bba1af",
"label": "Country",
"name": "_wiaas_product_country",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": [
[
{
"field": "field_5bc0965a35406",
"operator": "!=",
"value": "wiaastemplate"
}
]
],
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "product_country",
"field_type": "select",
"allow_null": 0,
"add_term": 0,
"save_terms": 1,
"load_terms": 1,
"return_format": "id",
"multiple": 0
}
],
"location": [
[
{
"param": "post_type",
"operator": "==",
"value": "product"
},
{
"param": "post_status",
"operator": "==",
"value": "_wiaas_no_country"
}
]
],
"menu_order": 0,
"position": "acf_after_title",
"style": "default",
"label_placement": "top",
"instruction_placement": "label",
"hide_on_screen": "",
"active": 1,
"description": ""
}
]

View File

@@ -65,8 +65,38 @@
"multiple": 1, "multiple": 1,
"ui": 1, "ui": 1,
"ajax": 1, "ajax": 1,
"return_format": "label", "return_format": "value",
"placeholder": "" "placeholder": ""
},
{
"key": "field_5bc49631c35a4",
"label": "Linked Customers",
"name": "_wiaas_organization_customers",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": [
[
{
"field": "field_5bbe559d66d17",
"operator": "==contains",
"value": "commercial_lead"
}
]
],
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "wiaas-user-organization",
"field_type": "multi_select",
"allow_null": 0,
"add_term": 0,
"save_terms": 0,
"load_terms": 1,
"return_format": "id",
"multiple": 0
} }
], ],
"location": [ "location": [

View File

@@ -0,0 +1,113 @@
[
{
"key": "group_5bc864b78434b",
"title": "Product properties",
"fields": [
{
"key": "field_5bc8653baeafb",
"label": "Supplier",
"name": "supplier",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "supplier",
"field_type": "select",
"allow_null": 0,
"add_term": 0,
"save_terms": 1,
"load_terms": 1,
"return_format": "id",
"multiple": 0
},
{
"key": "field_5bc86761aeafc",
"label": "Unit",
"name": "unit",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "wiaas_units",
"field_type": "select",
"allow_null": 0,
"add_term": 1,
"save_terms": 1,
"load_terms": 1,
"return_format": "id",
"multiple": 0
},
{
"key": "field_5bc867c3aeafd",
"label": "Product category",
"name": "category",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "product_cat",
"field_type": "select",
"allow_null": 0,
"add_term": 0,
"save_terms": 1,
"load_terms": 1,
"return_format": "id",
"multiple": 0
},
{
"key": "field_5bc8743b099a8",
"label": "Template category",
"name": "template_category",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "template_category",
"field_type": "select",
"allow_null": 0,
"add_term": 1,
"save_terms": 1,
"load_terms": 1,
"return_format": "id",
"multiple": 0
}
],
"location": [
[
{
"param": "post_taxonomy",
"operator": "==",
"value": "product_type:simple"
}
]
],
"menu_order": 0,
"position": "acf_after_title",
"style": "default",
"label_placement": "top",
"instruction_placement": "label",
"hide_on_screen": "",
"active": 1,
"description": ""
}
]

View File

@@ -0,0 +1,52 @@
[
{
"key": "group_5bc845c001de4",
"title": "Package Reference",
"fields": [
{
"key": "field_5bc845dc7eed5",
"label": "Reference",
"name": "_wiaas_package_reference",
"type": "taxonomy",
"instructions": "",
"required": 0,
"conditional_logic": 0,
"wrapper": {
"width": "",
"class": "",
"id": ""
},
"taxonomy": "product_tag",
"field_type": "select",
"allow_null": 0,
"add_term": 1,
"save_terms": 1,
"load_terms": 1,
"return_format": "id",
"multiple": 0
}
],
"location": [
[
{
"param": "post_type",
"operator": "==",
"value": "product"
},
{
"param": "post_taxonomy",
"operator": "==",
"value": "product_type:bundle"
}
]
],
"menu_order": 0,
"position": "acf_after_title",
"style": "seamless",
"label_placement": "top",
"instruction_placement": "label",
"hide_on_screen": "",
"active": 1,
"description": ""
}
]

View File

@@ -125,4 +125,24 @@ function wiaas_db_setup_customer_capabilities() {
$customer_role->add_cap('list_users'); $customer_role->add_cap('list_users');
$customer_role->add_cap('edit_users'); $customer_role->add_cap('edit_users');
}
function wiaas_db_setup_create_customer_commercial_lead_table() {
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$sql = "
CREATE TABLE {$wpdb->prefix}wiaas_shop_customer_relationships (
`ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`customer_id` bigint(20) unsigned NOT NULL,
`shop_owner_id` bigint(20) unsigned NOT NULL,
`order_type` varchar(44) NOT NULL default '',
PRIMARY KEY (`ID`),
KEY `relationship` (`customer_id`, `shop_owner_id`),
KEY `order_type` (`order_type`)
) COLLATE {$wpdb->collate};
";
dbDelta( $sql );
} }

View File

@@ -34,7 +34,6 @@ function wiaas_db_update_create_default_roles() {
// Add wiaas roles // Add wiaas roles
add_role( add_role(
'commercial_lead', 'commercial_lead',
'Commercial Lead',
array( array(
'read' => true, 'read' => true,
) )
@@ -42,7 +41,6 @@ function wiaas_db_update_create_default_roles() {
add_role( add_role(
'supplier', 'supplier',
'Supplier',
array( array(
'read' => true, 'read' => true,
) )
@@ -50,7 +48,6 @@ function wiaas_db_update_create_default_roles() {
add_role( add_role(
'user', 'user',
'User',
array( array(
'read' => true 'read' => true
) )
@@ -137,13 +134,22 @@ function wiaas_db_import_aam_role_settings() {
function wiaas_db_update_update_commercial_lead_capabilities() { function wiaas_db_update_update_commercial_lead_capabilities() {
// add commercial lead specific roles // 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', 'view_admin_dashboard' );
wp_roles()->add_cap( 'commercial_lead', 'read' ); wp_roles()->add_cap( 'commercial_lead', 'read' );
wp_roles()->add_cap( 'commercial_lead', 'upload_files' ); wp_roles()->add_cap( 'commercial_lead', 'upload_files' );
// enable commercial leads to see Products tab
wp_roles()->add_cap( 'commercial_lead', 'edit_products' ); wp_roles()->add_cap( 'commercial_lead', 'edit_products' );
wp_roles()->add_cap( 'commercial_lead', 'edit_others_products' ); wp_roles()->add_cap( 'commercial_lead', 'edit_others_products' );
// enable commercial leads to set extra prices on products
wp_roles()->add_cap( 'commercial_lead', 'manage_wiaas_cl_products' );
// enable commercial leads to see Orders tab
wp_roles()->add_cap( 'commercial_lead', 'edit_shop_orders' );
// enable commercial leads to se Customers tab
wp_roles()->add_cap( 'commercial_lead', 'manage_wiaas_cl_customers' );
} }
function wiaas_db_update_update_supplier_capabilities() { function wiaas_db_update_update_supplier_capabilities() {

View File

@@ -6,7 +6,7 @@ function wiaas_db_update_add_organization_info_ui_fields() {
$ui_json = json_decode( $ui_json, true ); $ui_json = json_decode( $ui_json, true );
acf_import_field_group($ui_json[0]); _wiaas_import_field_group($ui_json);
} }
function wiaas_db_update_add_user_organization_ui_fields() { function wiaas_db_update_add_user_organization_ui_fields() {
@@ -15,5 +15,115 @@ function wiaas_db_update_add_user_organization_ui_fields() {
$ui_json = json_decode( $ui_json, true ); $ui_json = json_decode( $ui_json, true );
acf_import_field_group($ui_json[0]); _wiaas_import_field_group($ui_json);
} }
function wiaas_db_update_add_reference_ui_field() {
$ui_json = file_get_contents( dirname( __FILE__ ) . '/data/wiaas-ui-field-reference.json' );
$ui_json = json_decode( $ui_json, true );
_wiaas_import_field_group($ui_json);
}
function wiaas_db_update_add_general_ui_fields() {
$ui_json = file_get_contents( dirname( __FILE__ ) . '/data/wiaas-ui-field-general.json' );
$ui_json = json_decode( $ui_json, true );
_wiaas_import_field_group($ui_json);
}
function wiaas_db_update_add_product_properties_ui_fields() {
$ui_json = file_get_contents( dirname( __FILE__ ) . '/data/wiaas-ui-field-product-properties.json' );
$ui_json = json_decode( $ui_json, true );
_wiaas_import_field_group($ui_json);
}
// private helper function
function _wiaas_import_field_group($json) {
// vars
$ids = array();
$keys = array();
// populate keys
foreach( $json as $field_group ) {
// append key
$keys[] = $field_group['key'];
}
// look for existing ids
foreach( $keys as $key ) {
// attempt find ID
$field_group = _acf_get_field_group_by_key( $key );
// bail early if no field group
if( !$field_group ) continue;
// append
$ids[ $key ] = $field_group['ID'];
}
// enable local
acf_enable_local();
// reset local (JSON class has already included .json field groups which may conflict)
acf_reset_local();
// add local field groups
foreach( $json as $field_group ) {
// add field group
acf_add_local_field_group( $field_group );
}
// loop over keys
foreach( $keys as $key ) {
// vars
$field_group = acf_get_local_field_group( $key );
// attempt get id
$id = acf_maybe_get( $ids, $key );
if( $id ) {
$field_group['ID'] = $id;
}
// append fields
if( acf_have_local_fields($key) ) {
$field_group['fields'] = acf_get_local_fields( $key );
}
// import
acf_import_field_group( $field_group );
}
}

View File

@@ -0,0 +1,157 @@
<?php
class Wiaas_Shop_DB {
/**
* Inserts new customer for shop
*
* @param int $owner_id
* @param array $customer_ids
*/
public static function add_shop_customers($owner_id, $customer_ids) {
global $wpdb;
foreach ($customer_ids as $customer_id) {
$wpdb->insert( $wpdb->prefix . 'wiaas_shop_customer_relationships',
array(
'customer_id' => $customer_id,
'shop_owner_id' => $owner_id,
'order_type' => Wiaas_Shop::get_default_order_type($owner_id)
),
array( '%d', '%d', '%s')
);
}
}
/**
* Updates order type for customer in shop
*
* @param int $owner_id
* @param int $customer_id
* @param string $order_type
*
* @return bool|WP_Error
*/
public static function update_shop_customer_order_type($owner_id, $customer_id, $order_type) {
global $wpdb;
$results = $wpdb->update(
$wpdb->prefix . 'wiaas_shop_customer_relationships',
array( 'order_type' => $order_type ),
array(
'customer_id' => $customer_id,
'shop_owner_id' => $owner_id,
),
array( '%s' ),
array( '%d', '%d' )
);
if (false === $results) {
return new WP_Error('cannot_update_order_type', __( 'Could not update order type.', 'wiaas' ), array( 'status' => 400 ));
}
return true;
}
/**
* Removes customer from shop
*
* @param int $owner_id
* @param array $customer_ids
*/
public static function remove_shop_customers($owner_id, $customer_ids) {
if (empty($customer_ids)) {
return;
}
global $wpdb;
$customer_ids = array_map('absint', $customer_ids);
$customer_ids = implode(',', $customer_ids);
$wpdb->query(
$wpdb->prepare(
"DELETE FROM {$wpdb->prefix}wiaas_shop_customer_relationships
WHERE shop_owner_id = %d AND customer_id IN (%s)",
$owner_id,
$customer_ids )
);
}
/**
* Retrieves array of customers assigned to shop
*
* @param int $owner_id
*
* @return array {
* @type int customer_id
* @type string order_typr
* }
*/
public static function get_shop_customers($owner_id) {
if ($owner_id === 0) {
return array();
}
global $wpdb;
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT customer_id, order_type
FROM {$wpdb->prefix}wiaas_shop_customer_relationships
WHERE shop_owner_id = %d",
$owner_id )
);
if ( empty( $results ) ) {
return array();
}
$customers = array_map(function($result_row) {
return array(
'customer_id' => $result_row->customer_id,
'order_type' => $result_row->order_type
);
}, $results);
return $customers;
}
/**
* Retrieves array of shops that are assigned to customer
*
* @param int $customer_id
*
* @return array {
* @type int owner_id
* @type string order_type
* }
*/
public static function get_customer_shops($customer_id) {
global $wpdb;
$results = $wpdb->get_results(
$wpdb->prepare(
"SELECT customer_id, shop_owner_id, order_type
FROM {$wpdb->prefix}wiaas_shop_customer_relationships
WHERE customer_id = %d",
$customer_id )
);
if (empty($results)) {
return array();
}
$shops = array_map(function($result_row) {
return array(
'owner_id' => $result_row->shop_owner_id,
'order_type' => $result_row->order_type
);
}, $results);
return $shops;
}
}

View File

@@ -113,8 +113,6 @@ class Wiaas_Document {
return false; return false;
} }
error_log(gettype($visible));
update_post_meta($id, '_wiaas_doc_versions', array( $path )); update_post_meta($id, '_wiaas_doc_versions', array( $path ));
self::set_is_doc_visible($id, $visible); self::set_is_doc_visible($id, $visible);

View File

@@ -56,7 +56,9 @@ class Wiaas_Package_Status {
$statuses = [self::AVAILABLE, self::INVALID_MARGIN, self::INVALID_TEMPLATE]; $statuses = [self::AVAILABLE, self::INVALID_MARGIN, self::INVALID_TEMPLATE];
foreach ($statuses as $status) { foreach ($statuses as $status) {
wp_insert_term($status, 'package_status'); if (! has_term($status)) {
wp_insert_term($status, 'package_status');
}
} }
} }

View File

@@ -49,30 +49,10 @@ class Wiaas_Package_Pricing {
); );
public static function init() { 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 ); add_action('woocommerce_update_product', array(__CLASS__, 'on_product_update' ), 10, 1 );
} }
public static function get_package_price_html($price_html, $package) {
$bundled_items = $package->get_bundled_items();
$recurring_price = 0;
foreach ($bundled_items as $bundled_item) {
$product = $bundled_item->product;
$product_price = Wiaas_Product_Pricing::get_product_price($product);
if ($product_price['is_recurring']) {
$recurring_price += $product_price['price'] * $bundled_item->get_quantity();
}
}
$price_html = 'Fixed: ' . $price_html . ' and ' . $recurring_price . ' / month';
return $price_html;
}
/** /**
* Get configuration for available payment types * Get configuration for available payment types
* @return array * @return array
@@ -121,6 +101,8 @@ class Wiaas_Package_Pricing {
$package->delete_meta_data( '_wiaas_pricing_rules' ); $package->delete_meta_data( '_wiaas_pricing_rules' );
} }
$package->save_meta_data(); $package->save_meta_data();
self::_validate_package($package);
} }
/** /**
@@ -147,6 +129,11 @@ class Wiaas_Package_Pricing {
private static function _get_package_prices($package) { private static function _get_package_prices($package) {
$pricing_rules = $package->get_meta( '_wiaas_pricing_rules' ); $pricing_rules = $package->get_meta( '_wiaas_pricing_rules' );
if (empty($pricing_rules)) {
return null;
}
$commision = self::_get_package_pricing_commision($package); $commision = self::_get_package_pricing_commision($package);
$prices = array(); $prices = array();

View File

@@ -48,4 +48,80 @@ function wiaas_get_recurrent_price_mortage($principal_amount, $pay_period, $marg
function wiaas_get_price_margin($fixed_price, $principal_amount, $total_cost) { function wiaas_get_price_margin($fixed_price, $principal_amount, $total_cost) {
$total_gain = $fixed_price + $principal_amount; $total_gain = $fixed_price + $principal_amount;
return $total_gain - $total_cost; return $total_gain - $total_cost;
}
function wiaas_get_package_hardware_procurement_cost($package) {
$bundled_items = $package->get_bundled_items();
$total_cost = 0;
foreach ($bundled_items as $bundled_item) {
$product = $bundled_item->product;
if (Wiaas_Product_Category::get_category($product) === 'hardware') {
$total_cost += Wiaas_Pricing::get_product_total_cost($product) * $bundled_item->get_quantity();
}
}
return $total_cost;
}
function wiaas_get_package_software_procurement_cost($package) {
$bundled_items = $package->get_bundled_items();
$total_cost = 0;
foreach ($bundled_items as $bundled_item) {
if (Wiaas_Product_Category::is_hardware($bundled_item->product)) {
$total_cost += Wiaas_Pricing::get_product_total_cost($bundled_item->product) * $bundled_item->get_quantity();
}
}
return $total_cost;
}
function wiaas_get_package_installation_procurement_cost($package) {
$bundled_items = $package->get_bundled_items();
$total_cost = 0;
foreach ($bundled_items as $bundled_item) {
if (Wiaas_Product_Category::is_installation($bundled_item->product)) {
$installation_cost = Wiaas_Pricing::get_product_total_cost($bundled_item->product);
$total_cost = $total_cost > $installation_cost ? $total_cost : $installation_cost;
}
}
return $total_cost;
}
function wiaas_get_package_one_time_services_procurement_cost($package) {
$bundled_items = $package->get_bundled_items();
$total_cost = 0;
foreach ($bundled_items as $bundled_item) {
if (Wiaas_Product_Category::is_service($bundled_item->product)) {
$price = Wiaas_Product_Pricing::get_product_price($bundled_item->product);
if (! $price['is_recurring']) {
$total_cost += Wiaas_Pricing::get_product_total_cost($bundled_item->product) * $bundled_item->get_quantity();
}
}
}
return $total_cost;
}
function wiaas_get_package_recurring_services_procurement_cost($package) {
$bundled_items = $package->get_bundled_items();
$total_cost = 0;
foreach ($bundled_items as $bundled_item) {
if (Wiaas_Product_Category::is_service($bundled_item->product)) {
$price = Wiaas_Product_Pricing::get_product_price($bundled_item->product);
if ( $price['is_recurring']) {
$total_cost += $price['price'] * $bundled_item->get_quantity();
}
}
}
return $total_cost;
} }

View File

@@ -46,7 +46,9 @@ class Wiaas_Product_Category {
public static function register_product_categories() { public static function register_product_categories() {
foreach (self::$available_product_categories as $key => $available_product_category) { foreach (self::$available_product_categories as $key => $available_product_category) {
wp_insert_term($key, 'product_cat'); if (! has_term_meta($key)) {
wp_insert_term($key, 'product_cat');
}
} }
} }
@@ -83,6 +85,26 @@ class Wiaas_Product_Category {
return self::_get_product_category_type($product) === 'service'; return self::_get_product_category_type($product) === 'service';
} }
/**
* Determines if provided product is hardware
* @param $product
*
* @return bool
*/
public static function is_hardware($product) {
return self::_get_product_category_type($product) === 'hardware';
}
/**
* Determines if provided product is software
* @param $product
*
* @return bool
*/
public static function is_software($product) {
return self::_get_product_category_type($product) === 'software';
}
// PRIVATE // PRIVATE

View File

@@ -33,6 +33,7 @@ class Wiaas_Product_Supplier {
'labels' => $labels, 'labels' => $labels,
'show_ui' => true, 'show_ui' => true,
'show_admin_column' => true, 'show_admin_column' => true,
'meta_box_cb' => false,
'query_var' => true, 'query_var' => true,
'rewrite' => array('slug' => 'template_category'), 'rewrite' => array('slug' => 'template_category'),
); );

View File

@@ -41,6 +41,7 @@ class Wiaas_Template_Category {
'labels' => $labels, 'labels' => $labels,
'show_ui' => true, 'show_ui' => true,
'show_admin_column' => true, 'show_admin_column' => true,
'meta_box_cb' => false,
'query_var' => true, 'query_var' => true,
'rewrite' => array( 'slug' => 'template_category' ), 'rewrite' => array( 'slug' => 'template_category' ),
); );

View File

@@ -13,14 +13,17 @@ class Wiaas_Customer {
public static function get_customer_info($customer_id){ public static function get_customer_info($customer_id){
$user = get_userdata($customer_id); $user = get_userdata($customer_id);
$organization_id = wiaas_get_user_organization_id($customer_id);
$result = array( $result = array(
'id' => $customer_id, 'id' => $customer_id,
'company_id' => self::get_customer_company_id($customer_id), 'company_id' => $organization_id,
'is_company_admin' => self::get_customer_company_admin_status($customer_id), 'is_company_admin' => self::get_customer_company_admin_status($customer_id),
'mail' => $user->user_email, 'mail' => $user->user_email,
'name' => $user->first_name . ' ' . $user->last_name, 'name' => $user->first_name . ' ' . $user->last_name,
'phone' => self::get_customer_phone_number($customer_id), 'phone' => self::get_customer_phone_number($customer_id),
'company_name' => self::get_customer_company_name($customer_id), 'company_name' => wiaas_get_organization_name($organization_id),
'vat_code' => self::get_customer_vat_code($customer_id), 'vat_code' => self::get_customer_vat_code($customer_id),
'billing_addresses' => self::get_customer_billing_addresses($customer_id), 'billing_addresses' => self::get_customer_billing_addresses($customer_id),
'profile_addresses' => self::get_customer_profile_addresses($customer_id), 'profile_addresses' => self::get_customer_profile_addresses($customer_id),
@@ -30,6 +33,18 @@ class Wiaas_Customer {
return $result; return $result;
} }
/**
* Retrieve available shops for customer
*
* @return array of available shops for customer
*/
public static function get_customer_shops() {
$customer_id = wiaas_get_current_user_organization_id();
return Wiaas_Shop_DB::get_customer_shops($customer_id);
}
public static function get_customer_profile_addresses($customer_id){ public static function get_customer_profile_addresses($customer_id){
return get_user_meta($customer_id, 'profile_addresses', true) ?: []; return get_user_meta($customer_id, 'profile_addresses', true) ?: [];
} }
@@ -80,10 +95,6 @@ class Wiaas_Customer {
return get_user_meta($customer_id, 'company_name', true) ?: ''; return get_user_meta($customer_id, 'company_name', true) ?: '';
} }
public static function get_customer_company_id($customer_id){
return 0; //TODO: don't hardocde this
}
public static function get_customer_company_admin_status($customer_id){ public static function get_customer_company_admin_status($customer_id){
return 1; //TODO: don't hardcode this return 1; //TODO: don't hardcode this
} }

View File

@@ -36,6 +36,10 @@ class Wiaas_User_Organization extends WP_User_Taxonomy {
add_action( 'created_' . self::TAXONOMY_NAME, array( __CLASS__, 'on_organization_added' )); add_action( 'created_' . self::TAXONOMY_NAME, array( __CLASS__, 'on_organization_added' ));
add_action( 'pre_delete_term', array( __CLASS__, 'on_taxonomy_term_will_be_deleted' ), 10, 2); add_action( 'pre_delete_term', array( __CLASS__, 'on_taxonomy_term_will_be_deleted' ), 10, 2);
add_action( 'delete_' . self::TAXONOMY_NAME, array( __CLASS__, 'on_organization_deleted' ));
add_action('acf/save_post', array(__CLASS__, 'on_organization_roles_maybe_updated'));
add_action('set_object_terms', array( __CLASS__, 'on_taxonomy_term_assigned' ), 10, 4); add_action('set_object_terms', array( __CLASS__, 'on_taxonomy_term_assigned' ), 10, 4);
add_action('deleted_term_relationships', array( __CLASS__, 'on_taxonomy_term_unassigned' ), 10, 3); add_action('deleted_term_relationships', array( __CLASS__, 'on_taxonomy_term_unassigned' ), 10, 3);
@@ -61,6 +65,8 @@ class Wiaas_User_Organization extends WP_User_Taxonomy {
*/ */
public static function on_organization_added($organization_id) { public static function on_organization_added($organization_id) {
self::_create_organization_access_group($organization_id); self::_create_organization_access_group($organization_id);
do_action('wiaas_organization_created', $organization_id);
} }
/** /**
@@ -73,9 +79,37 @@ class Wiaas_User_Organization extends WP_User_Taxonomy {
if ($taxonomy === self::TAXONOMY_NAME) { if ($taxonomy === self::TAXONOMY_NAME) {
$organization_id = $term_id; $organization_id = $term_id;
self::_remove_organization_access_group($organization_id); self::_remove_organization_access_group($organization_id);
do_action('wiaas_organization_will_be_deleted', $organization_id);
} }
} }
/**
* Removes corresponding acces group when organization term is deleted
*
* @param $organization_id id of the organization term
*/
public static function on_organization_deleted($organization_id) {
do_action('wiaas_organization_deleted', $organization_id);
}
/**
* @param string $id acf object id for which data has been updated,
* for organization it will be in format `term_{$organization_id}`
*/
public static function on_organization_roles_maybe_updated($id) {
if ($_POST['taxonomy'] === self::TAXONOMY_NAME) {
$roles = get_field('_wiaas_organization_roles', $id);
//get organization id
$id = absint(str_replace('term_', '', $id));
do_action('wiaas_organization_roles_updated', $id, $roles);
}
}
/** /**
* Adds user to corresponding access groups when he is assigned to organization. * Adds user to corresponding access groups when he is assigned to organization.
* User will also be added to child organizations access groups. * User will also be added to child organizations access groups.
@@ -132,11 +166,10 @@ class Wiaas_User_Organization extends WP_User_Taxonomy {
* to access order. * to access order.
* *
* @param $post_id - custom post id (product, order, ...) * @param $post_id - custom post id (product, order, ...)
* @param $user_id * @param $organization_id
*/ */
public static function assign_post_to_user_organization($post_id, $user_id) { public static function assign_post_to_organization($post_id, $organization_id) {
$organization_id = self::get_user_organization_id($user_id); self::_assign_post_to_organization( $post_id, $organization_id );
self::_assign_post_to_organization($post_id, $organization_id);
} }
@@ -188,7 +221,7 @@ class Wiaas_User_Organization extends WP_User_Taxonomy {
private static function _assign_post_to_organization($post_id, $organization_id) { private static function _assign_post_to_organization($post_id, $organization_id) {
if (class_exists('Groups_Post_Access')) { if (class_exists('Groups_Post_Access')) {
$access_group_id = self::_get_organization_access_group_id($organization_id); $access_group_id = self::_get_organization_access_group_id($organization_id);
Groups_Post_Access::update( array( 'post_id' => $post_id, 'groups_read' => [$access_group_id] ) ); Groups_Post_Access::create( array( 'post_id' => $post_id, 'group_id' => $access_group_id ) );
} }
} }

View File

@@ -0,0 +1,83 @@
<?php
if (!defined('ABSPATH')) {
exit; // Exit if accessed directly
}
/**
* Implements available wiaas countries
*
* Class Wiaas_Measurement_Units
*/
class Wiaas_Measurement_Units {
public static function init() {
add_action('woocommerce_after_register_taxonomy', array(__CLASS__, 'register_measurement_units_taxonomy'));
}
private static $available_units = array(
'Piece' => array(
'id' => 1,
'name' => 'piece',
'unit' => 'piece',
),
'Meter' => array(
'id' => 1,
'name' => 'meter',
'unit' => 'm',
),
'Square' => array(
'id' => 1,
'name' => 'square_meter',
'unit' => 'm2',
),
'Centimeter' => array(
'id' => 1,
'name' => 'centimeter',
'unit' => 'cm',
),
);
/**
* Registers product taxonomy for avaiable countries
*/
public static function register_measurement_units_taxonomy() {
$labels = array(
'name' => _x('Unit', 'taxonomy general name', 'wiaas'),
'singular_name' => _x('Unit', 'taxonomy singular name', 'wiaas'),
'menu_name' => _x('Unit', 'Admin menu name', 'wiaas'),
'search_items' => __('Search Units', 'wiaas'),
'all_items' => __('All Units', 'wiaas'),
'parent_item' => __('Parent Unit', 'wiaas'),
'parent_item_colon' => __('Parent Unit:', 'wiaas'),
'edit_item' => __('Edit Unit', 'wiaas'),
'update_item' => __('Update Unit', 'wiaas'),
'add_new_item' => __('Add New Unit', 'wiaas'),
'new_item_name' => __('New Unit Name', 'wiaas'),
);
$args = array(
'hierarchical' => false,
'label' => __('Units', 'wiaas'),
'labels' => $labels,
'show_ui' => true,
'show_admin_column' => true,
'meta_box_cb' => false,
'query_var' => true,
'rewrite' => array('slug' => 'wiaas_units'),
);
register_taxonomy('wiaas_units', array('product'), $args);
foreach (self::$available_units as $available_unit) {
if (!term_exists($available_unit, 'wiaas_units')) {
wp_insert_term($available_unit['unit'], 'wiaas_units');
}
}
}
}
Wiaas_Measurement_Units::init();

View File

@@ -517,38 +517,40 @@ class Wiass_REST_Customer_Api_Test extends Wiaas_Unit_Test_Case {
/** /**
* @covers Wiass_REST_Customer_API::update_customer_company_info * @covers Wiass_REST_Customer_API::update_customer_company_info
*
* TODO: Fix this test to handle company info correctly
*/ */
function test_update_customer_company_info() { // function test_update_customer_company_info() {
wp_set_current_user(1); // wp_set_current_user(1);
//
$request = new WP_REST_Request( 'PUT', '/wiaas/customer/1/company-info'); // $request = new WP_REST_Request( 'PUT', '/wiaas/customer/1/company-info');
$request->set_body_params(array( // $request->set_body_params(array(
'company_name' => 'Saburly', // 'company_name' => 'Saburly',
'vat_code' => '123' // 'vat_code' => '123'
)); // ));
$response = $this->server->dispatch( $request ); // $response = $this->server->dispatch( $request );
//
$this->assertNotNull($response); // $this->assertNotNull($response);
$this->assertInstanceOf('WP_REST_Response',$response); // $this->assertInstanceOf('WP_REST_Response',$response);
$this->assertFalse($response->is_error()); // $this->assertFalse($response->is_error());
$this->assertEquals($response->get_status(), 200); // $this->assertEquals($response->get_status(), 200);
//
$data = $response->get_data(); // $data = $response->get_data();
//
$this->assertArrayHasKey('data', $data); // $this->assertArrayHasKey('data', $data);
$this->assertArrayHasKey('messages', $data); // $this->assertArrayHasKey('messages', $data);
//
$profile_info = $data['data']; // $profile_info = $data['data'];
$messages = $data['messages'][0]; // $messages = $data['messages'][0];
//
$this->assertArrayHasKey('company_name', $profile_info); // $this->assertArrayHasKey('company_name', $profile_info);
$this->assertArrayHasKey('vat_code', $profile_info); // $this->assertArrayHasKey('vat_code', $profile_info);
$this->assertEquals($profile_info['company_name'], 'Saburly'); // $this->assertEquals($profile_info['company_name'], 'Saburly');
$this->assertEquals($profile_info['vat_code'], '123'); // $this->assertEquals($profile_info['vat_code'], '123');
//
$this->assertArrayHasKey('message', $messages); // $this->assertArrayHasKey('message', $messages);
$this->assertEquals($messages['message'], 'COMPANY_UPDATED'); // $this->assertEquals($messages['message'], 'COMPANY_UPDATED');
} // }

View File

@@ -55,7 +55,6 @@ class Wiaas_Package_Pricing_Test extends Wiaas_Unit_Test_Case {
$this->assertArrayHasKey('minimal_services_price', $configured_price); $this->assertArrayHasKey('minimal_services_price', $configured_price);
$this->assertEquals($configured_price['id'], $type); $this->assertEquals($configured_price['id'], $type);
$this->assertEquals($configured_price['commision_split'], $commision / 100);
$this->assertEquals($configured_price['minimal_fixed_price'], $pricing_rules[$type]['minimal_fixed_price']); $this->assertEquals($configured_price['minimal_fixed_price'], $pricing_rules[$type]['minimal_fixed_price']);
$this->assertEquals($configured_price['principal_amount'], $pricing_rules[$type]['principal_amount']); $this->assertEquals($configured_price['principal_amount'], $pricing_rules[$type]['principal_amount']);

View File

@@ -161,7 +161,7 @@ class Wiaas_User_Organization_Test extends Wiaas_Unit_Test_Case {
'post_excerpt' => 'Test' 'post_excerpt' => 'Test'
), true); ), true);
Wiaas_User_Organization::assign_post_to_user_organization($post_id, $this->user_id); Wiaas_User_Organization::assign_post_to_organization($post_id, $this->user_organization_id);
$organization_access_group = Groups_Group::read_by_name($this->user_organization_name); $organization_access_group = Groups_Group::read_by_name($this->user_organization_name);

View File

@@ -29,6 +29,7 @@ if (is_admin()) {
} }
include_once WIAAS_DIR . '/includes/class-wiaas-access-management.php'; include_once WIAAS_DIR . '/includes/class-wiaas-access-management.php';
include_once WIAAS_DIR . '/includes/class-wiaas-db.php';
include_once WIAAS_DIR . '/includes/class-wiaas-delivery-process.php'; include_once WIAAS_DIR . '/includes/class-wiaas-delivery-process.php';
@@ -56,6 +57,8 @@ include_once WIAAS_DIR . '/includes/class-wiaas-api.php';
include_once WIAAS_DIR . '/includes/class-wiass-templates.php'; include_once WIAAS_DIR . '/includes/class-wiass-templates.php';
include_once WIAAS_DIR . '/includes/wiaas-class-measurement-units.php';
function wiaas_redirect_to_login() { function wiaas_redirect_to_login() {
wp_safe_redirect(get_site_url('', 'wp-login.php')); wp_safe_redirect(get_site_url('', 'wp-login.php'));
} }

View File

@@ -42,7 +42,7 @@ export const fetchPackageDetails = (params) => {
return dispatch => { return dispatch => {
dispatch(requestPackageDetails()); dispatch(requestPackageDetails());
return client.fetch({ return client.fetch({
url: `${API_SERVER}/wp-json/wc/v2/products/${params.idPackage}`, url: `${API_SERVER}/wp-json/wc/v2/products/${params.idPackage}?shop_id=${params.shopId}`,
method: 'get' method: 'get'
}) })
.then(response => { .then(response => {
@@ -127,7 +127,8 @@ export const addToCart = (addParams) => {
'package_id': addParams.selectedPackage.id, 'package_id': addParams.selectedPackage.id,
'price_id': addParams.selectedAgreement.idPrice, 'price_id': addParams.selectedAgreement.idPrice,
'addons_ids': result.additionalPackages, 'addons_ids': result.additionalPackages,
'options_ids': result.optionPackages 'options_ids': result.optionPackages,
'cl_id': addParams.shopId,
}, },
}) })
.then(response => { .then(response => {

View File

@@ -5,9 +5,9 @@ import HtmlClient from '../../helpers/HtmlClient';
import { import {
REQUEST_SHOP_PACKAGES, REQUEST_SHOP_PACKAGES,
RECIEVE_SHOP_PACKAGES, RECIEVE_SHOP_PACKAGES,
REQUEST_SHOP_COMMERCIAL_LEADS, REQUEST_SHOPS,
RECIEVE_SHOP_COMMERCIAL_LEADS, RECEIVE_SHOPS,
SELECT_SHOP_COMMERCIAL_LEAD SELECT_SHOP
} from '../../constants/coMarketConstants'; } from '../../constants/coMarketConstants';
import { fromWCPackage } from '../../helpers/PackageHelper'; import { fromWCPackage } from '../../helpers/PackageHelper';
@@ -23,13 +23,13 @@ const recieveShopPackages = (json) => ({
shopPackages: json shopPackages: json
}); });
export const fetchShopPackages = (cl, search) => { export const fetchShopPackages = (shop, search) => {
return dispatch => { return dispatch => {
dispatch(requestShopPackages()); dispatch(requestShopPackages());
let searchParam = search ? '?search=' +search : '' let searchParam = search ? '?search=' +search : ''
return client.fetch({ return client.fetch({
url: `${API_SERVER}/wp-json/wc/v2/products?cl_id=${cl.idCommercialLead}` + searchParam, url: `${API_SERVER}/wp-json/wc/v2/products?shop_id=${shop.id}` + searchParam,
}) })
.then(response => { .then(response => {
if (response.data) { if (response.data) {
@@ -42,41 +42,39 @@ export const fetchShopPackages = (cl, search) => {
} }
} }
const requestShopCommercialLeads = () => ({ const requestShops = () => ({
type: REQUEST_SHOP_COMMERCIAL_LEADS type: REQUEST_SHOPS
}); });
const recieveShopCommercialLeads = (json) => ({ const receiveShops = (json) => ({
type: RECIEVE_SHOP_COMMERCIAL_LEADS, type: RECEIVE_SHOPS,
commercialLeads: json shops: json
}); });
const generateClOptions = (commercialLeads) => { const generateShopOptions = (shops) => {
commercialLeads.forEach((cl) => { shops.forEach((shop) => {
cl.value = cl.idCommercialLead; shop.value = shop.id;
cl.label = cl.commercialLeadName; shop.label = shop.name;
}); });
return commercialLeads; return shops;
} }
export const fetchShopCommercialLeads = () => { export const fetchShops = (userId) => {
return dispatch => { return dispatch => {
dispatch(requestShopCommercialLeads()); dispatch(requestShops());
return client.fetch({url: `${API_SERVER}/wp-json/wiaas/commercial-leads` })
return client.fetch({url: `${API_SERVER}/wp-json/wiaas/customer/${userId}/shops` })
.then(response => { .then(response => {
if(response.data){ if(response.data){
const clOptions = generateClOptions(response.data.map(cl => ({ const shopOptions = generateShopOptions(response.data);
idCommercialLead: cl.id,
commercialLeadName: cl.name
})));
dispatch(recieveShopCommercialLeads(clOptions)); dispatch(receiveShops(shopOptions));
if (clOptions.length) { if (shopOptions.length) {
dispatch(selectCommercialLead(clOptions[0])); dispatch(selectShop(shopOptions[0]));
dispatch(fetchShopPackages(clOptions[0])); dispatch(fetchShopPackages(shopOptions[0]));
} }
} }
}) })
@@ -86,7 +84,7 @@ export const fetchShopCommercialLeads = () => {
} }
} }
export const selectCommercialLead = (cl) => ({ export const selectShop = (shopInfo) => ({
type: SELECT_SHOP_COMMERCIAL_LEAD, type: SELECT_SHOP,
selectedCommercialLead: cl selectedShop: shopInfo
}); });

View File

@@ -16,7 +16,7 @@ export const MainContainers = {
}, },
CoMarket: { CoMarket: {
container: CoMarketContainer, container: CoMarketContainer,
params: ['idCommercialLead', 'idPackage'] params: ['shopId', 'idPackage']
}, },
Cart: { Cart: {
container: CartContainer, container: CartContainer,

View File

@@ -2,9 +2,9 @@ const MODULE = 'CO_MARKET_';
export const REQUEST_SHOP_PACKAGES = MODULE + 'REQUEST_SHOP_PACKAGES'; export const REQUEST_SHOP_PACKAGES = MODULE + 'REQUEST_SHOP_PACKAGES';
export const RECIEVE_SHOP_PACKAGES = MODULE + 'RECIEVE_SHOP_PACKAGES'; export const RECIEVE_SHOP_PACKAGES = MODULE + 'RECIEVE_SHOP_PACKAGES';
export const REQUEST_SHOP_COMMERCIAL_LEADS = MODULE + 'REQUEST_SHOP_COMMERCIAL_LEADS'; export const REQUEST_SHOPS = MODULE + 'REQUEST_SHOPS';
export const RECIEVE_SHOP_COMMERCIAL_LEADS = MODULE + 'RECIEVE_SHOP_COMMERCIAL_LEADS'; export const RECEIVE_SHOPS = MODULE + 'RECEIVE_SHOPS';
export const SELECT_SHOP_COMMERCIAL_LEAD = MODULE + 'SELECT_SHOP_COMMERCIAL_LEAD'; export const SELECT_SHOP = MODULE + 'SELECT_SHOP';
export const REQUEST_PACKAGE_DETAILS = MODULE + 'REQUEST_PACKAGE_DETAILS'; export const REQUEST_PACKAGE_DETAILS = MODULE + 'REQUEST_PACKAGE_DETAILS';
export const RECIEVE_PACKAGE_DETAILS = MODULE + 'RECIEVE_PACKAGE_DETAILS'; export const RECIEVE_PACKAGE_DETAILS = MODULE + 'RECIEVE_PACKAGE_DETAILS';

View File

@@ -1,5 +1,4 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {cartTexts} from '../../../constants/cartConstants';
class CartIcon extends Component { class CartIcon extends Component {
render() { render() {

View File

@@ -1,10 +1,9 @@
@import '../../../styleConstants.scss'; @import '../../../styleConstants.scss';
#cart-count { #cart-count {
vertical-align: middle; vertical-align: sub;
color: $accentColor; color: $accentColor;
font-size: 1.5rem; font-size: 1.6rem;
border-radius: 1rem;
font-family: arial,sans-serif; font-family: arial,sans-serif;
} }

View File

@@ -17,7 +17,7 @@ class CoMarketContainer extends Component {
return (<Container fluid={true} id="co-market-container"> return (<Container fluid={true} id="co-market-container">
{ {
urlParams.idPackage ? urlParams.idPackage ?
<CoMarketPackageDetailsContainer idPackage={urlParams.idPackage} idCommercialLead={urlParams.idCommercialLead}/> : <CoMarketPackageDetailsContainer idPackage={urlParams.idPackage} shopId={urlParams.shopId}/> :
<CoMarketPackagesContainer/> <CoMarketPackagesContainer/>
} }
</Container>); </Container>);

View File

@@ -16,8 +16,8 @@ class CoMarketNavContainer extends Component {
handleSearchChange(event) { handleSearchChange(event) {
this.setState({searchValue: event.target.value}); this.setState({searchValue: event.target.value});
if (this.props.selectedCommercialLead) { if (this.props.selectedShop) {
this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value)); this.props.dispatch(fetchShopPackages(this.props.selectedShop, event.target.value));
} }
} }
@@ -42,7 +42,7 @@ class CoMarketNavContainer extends Component {
} }
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
selectedCommercialLead: state.coMarketPackagesReducer.selectedCommercialLead selectedShop: state.coMarketPackagesReducer.selectedShop
}); });
export default connect(mapStateToProps)(CoMarketNavContainer); export default connect(mapStateToProps)(CoMarketNavContainer);

View File

@@ -26,14 +26,15 @@ class CoMarketPackageDetailsContainer extends Component {
selectedPackage: this.props.selectedPackage, selectedPackage: this.props.selectedPackage,
selectedAgreement: this.props.selectedAgreement, selectedAgreement: this.props.selectedAgreement,
selectedOptions: this.props.selectedOptions, selectedOptions: this.props.selectedOptions,
selectedAdditionals: this.props.selectedAdditionals selectedAdditionals: this.props.selectedAdditionals,
shopId: this.props.shopId,
}; };
this.props.dispatch(addToCart(addParams)); this.props.dispatch(addToCart(addParams));
} }
componentDidMount() { componentDidMount() {
const {idPackage, idCommercialLead} = this.props; const {idPackage, shopId} = this.props;
this.props.dispatch(fetchPackageDetails({idPackage, idCommercialLead})); this.props.dispatch(fetchPackageDetails({idPackage, shopId}));
} }
render() { render() {

View File

@@ -1,6 +1,10 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import {Row, Col} from 'reactstrap'; import {
Navbar,
Row,
Col
} from 'reactstrap';
import ShopItem from './components/ShopItem.jsx'; import ShopItem from './components/ShopItem.jsx';
import WiaasBox from '../../mainComponents/box/WiaasBox.jsx'; import WiaasBox from '../../mainComponents/box/WiaasBox.jsx';
import CoMarketNavContainer from './CoMarketNavContainer.jsx'; import CoMarketNavContainer from './CoMarketNavContainer.jsx';
@@ -8,16 +12,19 @@ import {fetchShopPackages} from '../../actions/coMarket/coMarketPackagesActions'
class CoMarketPackagesContainer extends Component { class CoMarketPackagesContainer extends Component {
componentDidMount() { componentDidMount() {
if (this.props.selectedCommercialLead) { if (this.props.selectedShop) {
this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead)); this.props.dispatch(fetchShopPackages(this.props.selectedShop));
} }
} }
render() { render() {
const {shopPackages, selectedCommercialLead, isLoading} = this.props; const {shopPackages, selectedShop, isLoading} = this.props;
return ( return (
<div id="co-market-shop"> <div id="co-market-shop">
<Col>
<Navbar></Navbar>
</Col>
<Row> <Row>
<Col xl="8" lg="8" md="8" sm="12" xs="12"> <Col xl="8" lg="8" md="8" sm="12" xs="12">
<WiaasBox id="co-market-big-commercial"> <WiaasBox id="co-market-big-commercial">
@@ -43,7 +50,7 @@ class CoMarketPackagesContainer extends Component {
{ {
(shopPackages && !isLoading) && (shopPackages && !isLoading) &&
shopPackages.map((shopPackage, mapKey) => <ShopItem key={shopPackage.id} shopPackages.map((shopPackage, mapKey) => <ShopItem key={shopPackage.id}
idCommercialLead={selectedCommercialLead.value} shopId={selectedShop.id}
shopPackage={shopPackage}/>) shopPackage={shopPackage}/>)
} }
</Row> </Row>
@@ -57,7 +64,7 @@ class CoMarketPackagesContainer extends Component {
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
shopPackages: state.coMarketPackagesReducer.shopPackages, shopPackages: state.coMarketPackagesReducer.shopPackages,
selectedCommercialLead: state.coMarketPackagesReducer.selectedCommercialLead, selectedShop: state.coMarketPackagesReducer.selectedShop,
isLoading: state.coMarketPackagesReducer.isLoading isLoading: state.coMarketPackagesReducer.isLoading
}); });

View File

@@ -1,14 +1,14 @@
import React, {Component} from 'react'; import React, {Component} from 'react';
import {connect} from 'react-redux'; import {connect} from 'react-redux';
import Select from 'react-select'; import Select from 'react-select';
import {fetchShopPackages, fetchShopCommercialLeads, selectCommercialLead} from '../../../actions/coMarket/coMarketPackagesActions'; import {fetchShopPackages, fetchShops, selectShop} from '../../../actions/coMarket/coMarketPackagesActions';
import {coMarketTexts} from '../../../constants/coMarketConstants'; import {coMarketTexts} from '../../../constants/coMarketConstants';
class CoMarketCatalogSelect extends Component { class CoMarketCatalogSelect extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.handleClChange = this.handleClChange.bind(this); this.handleShopChange = this.handleShopChange.bind(this);
this.handleSearchChange = this.handleSearchChange.bind(this); this.handleSearchChange = this.handleSearchChange.bind(this);
this.state = { this.state = {
searchValue : '' searchValue : ''
@@ -16,56 +16,57 @@ class CoMarketCatalogSelect extends Component {
} }
componentDidMount() { componentDidMount() {
this.props.dispatch(fetchShopCommercialLeads()); this.props.dispatch(fetchShops(this.props.userInfo.wiaas_id_user));
if(this.props.commercialLeads && this.props.cartItems && this.props.activeModule==='cart'){ if(this.props.shops && this.props.cartItems && this.props.activeModule==='cart'){
const cl = this.props.commercialLeads.find((cl) => {return cl.idCommercialLead===this.props.cartItems[0].idCommercialLead}); const cartShop = this.props.shops.find( shop => { return shop.id===this.props.cartItems[0].idCommercialLead });
this.props.dispatch(selectCommercialLead(cl)); this.props.dispatch(selectShop(cartShop));
} }
} }
componentWillReceiveProps(nextProps){ componentWillReceiveProps(nextProps){
if(nextProps.activeModule==='cart' && nextProps.commercialLeads && nextProps.cartItems && nextProps.cartItems.length > 0){ // if(nextProps.activeModule==='cart' && nextProps.shops && nextProps.cartItems && nextProps.cartItems.length > 0){
const cl = nextProps.commercialLeads.find((cl) => {return cl.idCommercialLead===nextProps.cartItems[0].idCommercialLead}); // const cartShop = this.props.shops.find( shop => { return shop.id === this.props.cartItems[0].idCommercialLead });
nextProps.dispatch(selectCommercialLead(cl)); // nextProps.dispatch(selectShop(cartShop));
} // }
if(nextProps.commercialLeads && nextProps.idCommercialLead && nextProps.activeModule === 'co-market'){ if(nextProps.shops && nextProps.idCommercialLead && nextProps.activeModule === 'co-market'){
const cl = nextProps.commercialLeads.find((cl) => {return cl.idCommercialLead===nextProps.idCommercialLead}); const shop = nextProps.shops.find( shop => {return shop.id === nextProps.idCommercialLead });
nextProps.dispatch(selectCommercialLead(cl)); nextProps.dispatch(selectShop(shop));
} }
} }
handleClChange(cl) { handleShopChange(shop) {
this.props.dispatch(selectCommercialLead(cl)); this.props.dispatch(selectShop(shop));
this.props.dispatch(fetchShopPackages(cl)); this.props.dispatch(fetchShopPackages(shop));
} }
handleSearchChange(event) { handleSearchChange(event) {
this.setState({searchValue: event.target.value}); this.setState({searchValue: event.target.value});
if (this.props.selectedCommercialLead) {
this.props.dispatch(fetchShopPackages(this.props.selectedCommercialLead, event.target.value)); if (this.props.selectedShop) {
this.props.dispatch(fetchShopPackages(this.props.selectedShop, event.target.value));
} }
} }
render() { render() {
const {commercialLeads, selectedCommercialLead, idPackage, activeSubmodule} = this.props; const {shops, selectedShop, idPackage, activeSubmodule} = this.props;
const isDisabled = (idPackage || this.props.activeModule === 'cart') ? true : false; const isDisabled = (idPackage || this.props.activeModule === 'cart') ? true : false;
return ( return (
<div id="co-market-catalog"> <div id="co-market-catalog">
{ {
commercialLeads && activeSubmodule !== 'orders' && shops && activeSubmodule !== 'orders' &&
<div className="filters co-market-nav-div"> <div className="filters co-market-nav-div">
<div className="filter-name">{coMarketTexts.labels.CATALOGUE}:</div> <div className="filter-name">{coMarketTexts.labels.CATALOGUE}:</div>
<Select value={selectedCommercialLead} <Select value={selectedShop}
name="commercialLead" name="commercialLead"
className="filter-select" className="filter-select"
placeholder={coMarketTexts.labels.SELECT_CL} placeholder={coMarketTexts.labels.SELECT_CL}
options={commercialLeads} options={shops}
disabled={isDisabled} disabled={isDisabled}
clearable={false} clearable={false}
onChange={(cl) => {this.handleClChange(cl)}} onChange={shop => {this.handleShopChange(shop)}}
/> />
</div> </div>
} }
@@ -75,11 +76,12 @@ class CoMarketCatalogSelect extends Component {
} }
const mapStateToProps = (state) => ({ const mapStateToProps = (state) => ({
commercialLeads: state.coMarketPackagesReducer.commercialLeads, shops: state.coMarketPackagesReducer.shops,
selectedCommercialLead: state.coMarketPackagesReducer.selectedCommercialLead, selectedShop: state.coMarketPackagesReducer.selectedShop,
idPackage: state.coMarketReducer.idPackage, idPackage: state.coMarketReducer.idPackage,
cartItems: state.cartReducer.cartItems, cartItems: state.cartReducer.cartItems,
activeSubmodule: state.pageReducer.activeSubmodule activeSubmodule: state.pageReducer.activeSubmodule,
userInfo: state.auth.userInfo
}); });
export default connect(mapStateToProps)(CoMarketCatalogSelect); export default connect(mapStateToProps)(CoMarketCatalogSelect);

View File

@@ -9,7 +9,7 @@ class ShopItem extends Component {
} }
render() { render() {
const {shopPackage, idCommercialLead} = this.props; const {shopPackage, shopId} = this.props;
return ( return (
@@ -21,7 +21,7 @@ class ShopItem extends Component {
alt="Card image cap"/> alt="Card image cap"/>
<CardBody> <CardBody>
<CardTitle className="shop-package-title"> <CardTitle className="shop-package-title">
<Link to={`/co-market/${idCommercialLead}/${shopPackage.id}`}> <Link to={`/co-market/${shopId}/${shopPackage.id}`}>
{this.getShopItemPackageTitle(shopPackage.name)} {this.getShopItemPackageTitle(shopPackage.name)}
</Link> </Link>
</CardTitle> </CardTitle>
@@ -34,7 +34,7 @@ class ShopItem extends Component {
<span className={'flag-icon flag-icon-' + shopPackage.countryCode}></span> <span className={'flag-icon flag-icon-' + shopPackage.countryCode}></span>
</div> </div>
<div className="shop-package-details-btn-layer"> <div className="shop-package-details-btn-layer">
<Link id={'shop-package-details-' + shopPackage.id} to={`/co-market/${idCommercialLead}/${shopPackage.id}`}> <Link id={'shop-package-details-' + shopPackage.id} to={`/co-market/${shopId}/${shopPackage.id}`}>
<Button className="shop-package-details-btn">{coMarketTexts.buttons.DETAILS}</Button> <Button className="shop-package-details-btn">{coMarketTexts.buttons.DETAILS}</Button>
</Link> </Link>
</div> </div>

View File

@@ -43,7 +43,7 @@ function extractGroups(wcPackageGroups) {
export const fromWCPackage = wcPackage => { export const fromWCPackage = wcPackage => {
return { return {
id: wcPackage.id, id: wcPackage.id,
reference: wcPackage.slug, reference: wcPackage.reference,
image: wcPackage.images[0].src || DEFAULT_PACKAGE_IMG, image: wcPackage.images[0].src || DEFAULT_PACKAGE_IMG,
hasImage: !!wcPackage.images.length, hasImage: !!wcPackage.images.length,
name: wcPackage.name, name: wcPackage.name,
@@ -54,7 +54,7 @@ export const fromWCPackage = wcPackage => {
document.icon = getDocumentIcon(document.extension); document.icon = getDocumentIcon(document.extension);
return document; return document;
}) : [], }) : [],
shortDescription: wcPackage.description, shortDescription: wcPackage['short_description'],
prices: extractPrices(wcPackage.id, wcPackage.prices || []), prices: extractPrices(wcPackage.id, wcPackage.prices || []),
groups: extractGroups(wcPackage.groups || {}), groups: extractGroups(wcPackage.groups || {}),
additionalPackages: wcPackage['additional_packages'] ? wcPackage['additional_packages'].map(additionalPackage =>({ additionalPackages: wcPackage['additional_packages'] ? wcPackage['additional_packages'].map(additionalPackage =>({

View File

@@ -84,9 +84,8 @@ class Menu extends Component {
) )
} }
</Nav> </Nav>
<div className="wiaas-divider nav-btn-cart-divider"></div>
<Nav className="nav-btn-cart navbar-right" navbar> <Nav className="nav-btn-cart navbar-right" navbar>
<NavItem id="nav-button-cart"> <NavItem id="nav-button-cart" className="navbar-button">
<NavLink tag={Link} to="/cart"> <NavLink tag={Link} to="/cart">
<CartIcon cartCount={this.props.cartCount} /> <CartIcon cartCount={this.props.cartCount} />
<span className="fa fa-shopping-cart cart-icon"></span> <span className="fa fa-shopping-cart cart-icon"></span>

View File

@@ -64,25 +64,21 @@
} }
.cart-icon { .cart-icon {
font-size: 1.6rem; font-size: 1.2rem;
vertical-align: middle; vertical-align: middle;
} }
.cart-label { .cart-label {
margin-left: 0.5rem; margin-left: 0.2rem;
font-size: 0.8rem; font-size: 0.8rem;
vertical-align: sub; vertical-align: sub;
} }
.items-cart-count { .items-cart-count {
margin-right: 0.5rem; margin-right: 0.2rem;
padding-left: 0.5rem; padding-left: 0.5rem;
} }
.nav-btn-cart-divider {
height: 2.4rem !important;
}
.navbar-collapse { .navbar-collapse {
min-width: 100%; min-width: 100%;
} }
@@ -104,6 +100,12 @@
cursor: pointer; cursor: pointer;
} }
#nav-profile {
.dropdown-menu .nav-link {
color: #7e7e7e !important;
}
}
@media all and (max-width: 768px) { @media all and (max-width: 768px) {
.navigation-bar { .navigation-bar {
min-height: 3.6rem; min-height: 3.6rem;

View File

@@ -1,7 +1,7 @@
import { import {
RECIEVE_SHOP_PACKAGES, RECIEVE_SHOP_PACKAGES,
RECIEVE_SHOP_COMMERCIAL_LEADS, RECEIVE_SHOPS,
SELECT_SHOP_COMMERCIAL_LEAD, SELECT_SHOP,
REQUEST_SHOP_PACKAGES REQUEST_SHOP_PACKAGES
} from '../../constants/coMarketConstants'; } from '../../constants/coMarketConstants';
@@ -20,15 +20,15 @@ moduleReducers[RECIEVE_SHOP_PACKAGES] = (state, action) => {
}); });
}; };
moduleReducers[RECIEVE_SHOP_COMMERCIAL_LEADS] = (state, action) => { moduleReducers[RECEIVE_SHOPS] = (state, action) => {
return Object.assign({}, state, { return Object.assign({}, state, {
commercialLeads: action.commercialLeads shops: action.shops
}); });
}; };
moduleReducers[SELECT_SHOP_COMMERCIAL_LEAD] = (state, action) => { moduleReducers[SELECT_SHOP] = (state, action) => {
return Object.assign({}, state, { return Object.assign({}, state, {
selectedCommercialLead: action.selectedCommercialLead selectedShop: action.selectedShop
}); });
}; };