Merge branch 'bundle-cost-summary' into 'master'

Bundle cost summary

See merge request saburly/wiaas/new-wiaas!35
This commit was merged in pull request #35.
This commit is contained in:
Nedim Uka
2018-10-19 10:28:24 +00:00
18 changed files with 703 additions and 336 deletions

View File

@@ -30,19 +30,9 @@
}
#wiaas_package_pricing_rules > .wiaas-pricing-rule {
border-color:#dfdfdf;
border-width:1px;
border-style:solid;
-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;
border:1px #dfdfdf solid;
background-color:#fff;
width: 95%;
}
#wiaas_package_pricing_rules > .wiaas-pricing-rule .section {
@@ -133,4 +123,12 @@
#adminmenu #toplevel_page_wiaas-cl-packages div.wp-menu-image::before {
font-family: WooCommerce!important;
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

@@ -10,6 +10,28 @@ class Wiaas_Admin_Package {
require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-linked-packages.php';
require_once dirname( __FILE__ ) . '/package/class-wiaas-admin-package-types.php';
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;
}
}

View File

@@ -11,12 +11,49 @@ class Wiaas_Admin_Package_Pricing {
public static function init() {
add_action( 'woocommerce_product_data_tabs', array( __CLASS__, 'package_data_tabs' ) );
add_action( 'woocommerce_product_data_panels', array( __CLASS__, 'package_data_panel' ) );
add_action( 'admin_menu', array(__CLASS__, 'add_package_pricing_editor_page') );
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();
}
/**
* 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
*/
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);
$commission = Wiaas_Package_Pricing::get_package_pricing_commission($package);
$max_cost_margin = Wiaas_Package_Pricing::get_package_max_cost_margin($package);
include 'views/html-package-pricing.php';
// 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
* @param $post_id
* @param $post
* Save posted package pricing information
*
* @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(
wc_get_product( $post_id ),
$_POST['wiaas_pricing_rules'],
$_POST['wiaas_pricing_rules_commision'],
$_POST['wiaas_max_cost_margin']);
wc_get_product( $package_id ),
$pricing_rules,
$commission,
$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 ) {
$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">
<h4 class="first"><?php echo $pay_type['title']; ?>
<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
woocommerce_wp_checkbox(
array(

View File

@@ -10,7 +10,6 @@ class Wiaas_template {
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_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'));
// Enqueue scripts.
@@ -198,21 +197,6 @@ class Wiaas_template {
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();

View File

@@ -38,7 +38,8 @@ class Wiaas_Access_Management {
// if product is not bundle or it not completed set it visible only for admin
if ($product->get_type() !== 'bundle' ||
$product->get_status() !== 'publish') {
$product->get_status() !== 'publish' ||
empty(Wiaas_Package_Pricing::get_package_prices($product))) {
$access_group = Groups_Group::read_by_name('admin');
} else {

View File

@@ -33,7 +33,10 @@ class Wiaas_Admin {
$plugin_url = untrailingslashit( plugins_url( '/', WIAAS_FILE ) );
wp_enqueue_style( 'wiaas_admin_menu', $plugin_url . '/assets/css/menu.css' );
wp_enqueue_style( 'wiaas_admin_packages', $plugin_url . '/assets/css/package.css' );
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

@@ -6,17 +6,19 @@ class Wiaas_Product {
require_once dirname( __FILE__ ) . '/product/class-wiaas-product-category.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'));
}
/**
* 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
*
* @return mixed
*/
public static function define_product_capabilities($args) {
public static function manage_product_settings($args) {
$args['capabilities'] = array(
'edit_post' => 'edit_product',
@@ -28,6 +30,10 @@ class Wiaas_Product {
'read_private_posts' => 'read_private_products',
'create_posts' => 'create_products', // use `create_products` instead of default `edit_products`
);
$args['supports'] = array( 'title', 'thumbnail' );
return $args;
}
}

View File

@@ -56,7 +56,9 @@ class Wiaas_Package_Status {
$statuses = [self::AVAILABLE, self::INVALID_MARGIN, self::INVALID_TEMPLATE];
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() {
add_filter('woocommerce_bundle_price_html', array( __CLASS__, 'get_package_price_html' ), 10, 2);
add_action('woocommerce_update_product', array(__CLASS__, 'on_product_update' ), 10, 1 );
}
public static function get_package_price_html($price_html, $package) {
$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
* @return array
@@ -121,6 +101,8 @@ class Wiaas_Package_Pricing {
$package->delete_meta_data( '_wiaas_pricing_rules' );
}
$package->save_meta_data();
self::_validate_package($package);
}
/**
@@ -147,6 +129,11 @@ class Wiaas_Package_Pricing {
private static function _get_package_prices($package) {
$pricing_rules = $package->get_meta( '_wiaas_pricing_rules' );
if (empty($pricing_rules)) {
return null;
}
$commision = self::_get_package_pricing_commision($package);
$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) {
$total_gain = $fixed_price + $principal_amount;
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() {
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';
}
/**
* 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

View File

@@ -54,7 +54,7 @@ export const fromWCPackage = wcPackage => {
document.icon = getDocumentIcon(document.extension);
return document;
}) : [],
shortDescription: wcPackage.description,
shortDescription: wcPackage['short_description'],
prices: extractPrices(wcPackage.id, wcPackage.prices || []),
groups: extractGroups(wcPackage.groups || {}),
additionalPackages: wcPackage['additional_packages'] ? wcPackage['additional_packages'].map(additionalPackage =>({