Custom fees plugin problem
-
Hi,
I have a custom plugin (developed by help of AI) to add custom packaging cost (unfortunatelly I’m not that good at programming in this level).
The currency switcher plugin works well with default Subtotal and Shipping costs, but doesn’t switch my custom fee. Can you help me what is missing from my code to cooperate with the currency switcher?

Here is my plugin code below.
It calculates the required containers based on the shipping class and shipping class capacity set on the plugin’s settings page. The Shipping price also multiplied by the number of containers.<?php
/*
* Plugin Name: WooCommerce Dynamic Packing Charge
* Description: Extra packaging fee for every X products, shipping fee multiplied by the number of containers. Separate step setting for each shipping class, plus option for mixing.
* Version: 1.7.1
* Requires at least: 5.2
* Requires PHP: 7.2
* Author: Gal
* Text Domain: packing-charge
* Requires Plugins: woocommerce
*/
if ( ! defined( 'ABSPATH' ) ) exit;
/* Settings link */
add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), function( $links ) {
$settings_url = add_query_arg( array( 'page' => 'wc-settings', 'tab' => 'packing_charges' ), admin_url('admin.php') );
$settings_link = '<a href="' . esc_url( $settings_url ) . '">' . __('Settings', 'packing-charge') . '</a>';
array_unshift($links, $settings_link);
return $links;
});
/* Settings tab */
add_filter( 'woocommerce_settings_tabs_array', function( $tabs ) {
$tabs['packing_charges'] = __( 'Packing Charges', 'packing-charge' );
return $tabs;
}, 999 );
add_action( 'woocommerce_settings_tabs_packing_charges', function() {
woocommerce_admin_fields( pacs_get_settings() );
});
add_action( 'woocommerce_update_options_packing_charges', function() {
woocommerce_update_options( pacs_get_settings() );
});
/* Settings fields */
function pacs_get_settings() {
$settings = array(
array(
'name' => __( 'Packing Charge Settings', 'packing-charge' ),
'type' => 'title',
'id' => 'pacs_section_title'
),
array(
'name' => __( 'Enable Packing Charge', 'packing-charge' ),
'type' => 'checkbox',
'id' => 'pacs_enable',
'default' => 'no'
),
array(
'name' => __( 'Calculation Type', 'packing-charge' ),
'type' => 'select',
'id' => 'pacs_calculation_type',
'options' => array(
'fixed' => __( 'Fixed (Flat Fee)', 'packing-charge' ),
'percentage' => __( 'Percentage', 'packing-charge' ),
'per_step' => __( 'Per step (every X items)', 'packing-charge' )
),
'default' => 'fixed'
),
array(
'name' => __( 'Packing Charge Amount', 'packing-charge' ),
'type' => 'number',
'id' => 'pacs_amount',
'default' => '0',
'custom_attributes' => array( 'min' => '0' )
),
array(
'name' => __( 'Step (products per fee)', 'packing-charge' ),
'type' => 'number',
'id' => 'pacs_step',
'default' => '1',
'custom_attributes' => array( 'min' => '1' )
),
array(
'name' => __( 'Packing Charge Label', 'packing-charge' ),
'type' => 'text',
'id' => 'pacs_label',
'default' => 'Packaging fee'
),
array(
'name' => __( 'Packing Container Label', 'packing-charge' ),
'type' => 'text',
'id' => 'pacs_container_label',
'default' => 'Container'
),
array(
'name' => __( 'Packing Unit Label', 'packing-charge' ),
'type' => 'text',
'id' => 'pacs_unit_label',
'default' => 'db'
),
array(
'name' => __( 'Packing Counts Per Shipping Class', 'packing-charge' ),
'type' => 'checkbox',
'id' => 'pacs_counts_per_shipping_class',
'default' => 'no'
),
array(
'name' => __( 'Step for products without shipping class', 'packing-charge' ),
'type' => 'number',
'id' => 'pacs_step_none',
'default' => '1',
'custom_attributes' => array( 'min' => '1' )
),
array(
'name' => __( 'Allow mixing shipping classes into one container', 'packing-charge' ),
'type' => 'checkbox',
'id' => 'pacs_allow_mix',
'default' => 'yes'
),
);
$shipping_classes = WC()->shipping->get_shipping_classes();
foreach ( $shipping_classes as $class ) {
$settings[] = array(
'name' => sprintf( __( 'Step for %s', 'packing-charge' ), $class->name ),
'type' => 'number',
'id' => 'pacs_step_' . $class->slug,
'default' => '1',
'custom_attributes' => array( 'min' => '1' )
);
}
$settings[] = array(
'type' => 'sectionend',
'id' => 'pacs_section_end'
);
return $settings;
}
/* Container calculation */
function pacs_calculate_groups() {
$allow_mix = get_option( 'pacs_allow_mix', 'yes' ) === 'yes';
$per_class = get_option( 'pacs_counts_per_shipping_class' ) === 'yes';
$global_step = max( 1, intval( get_option( 'pacs_step', 1 ) ) );
$none_step = max( 1, intval( get_option( 'pacs_step_none', 1 ) ) );
if ( ! $per_class ) {
$qty = WC()->cart->get_cart_contents_count();
return max( 1, ceil( $qty / $global_step ) );
}
if ( ! $allow_mix ) {
$groups = 0;
foreach ( WC()->cart->get_cart() as $item ) {
$qty = intval( $item['quantity'] );
$class_id = $item['data']->get_shipping_class_id();
if ( $class_id ) {
$class = get_term( $class_id, 'product_shipping_class' );
$step = max( 1, intval( get_option( 'pacs_step_' . $class->slug, 1 ) ) );
} else {
$step = $none_step;
}
$groups += ceil( $qty / $step );
}
return max( 1, $groups );
}
// Greedy: fill smallest container first
$classes = [];
foreach ( WC()->cart->get_cart() as $item ) {
$qty = intval( $item['quantity'] );
$class_id = $item['data']->get_shipping_class_id();
if ( $class_id ) {
$class = get_term( $class_id, 'product_shipping_class' );
$cap = max( 1, intval( get_option( 'pacs_step_' . $class->slug, 1 ) ) );
} else {
$cap = $none_step;
}
$classes[] = ['qty' => $qty, 'cap' => $cap];
}
usort($classes, function($a, $b) {
return $a['cap'] <=> $b['cap'];
});
$containers = 0;
while (true) {
$remaining = 0;
foreach ($classes as $c) { $remaining += $c['qty']; }
if ($remaining <= 0) break;
// actual container capacity: smallest available class
$cap = 0;
foreach ($classes as $c) {
if ($c['qty'] > 0) { $cap = $c['cap']; break; }
}
if ($cap == 0) break;
$containers++;
$space_left = $cap;
// first smallest class
for ($i = 0; $i < count($classes); $i++) {
if ($space_left <= 0) break;
if ($classes[$i]['qty'] <= 0) continue;
$put = min($classes[$i]['qty'], $space_left);
$classes[$i]['qty'] -= $put;
$space_left -= $put;
}
}
return max(1, $containers);
}
/* Add packing fee as real WooCommerce fee to calculate total */
add_action( 'woocommerce_cart_calculate_fees', function( $cart ) {
if ( get_option( 'pacs_enable' ) !== 'yes' ) return;
$amount = (float) get_option( 'pacs_amount', 0 );
$type = get_option( 'pacs_calculation_type', 'fixed' );
$groups = pacs_calculate_groups();
$subtotal = (float) $cart->get_subtotal();
// Calculating fee
$fee = 0.0;
if ( $type === 'fixed' ) {
$fee = $groups * $amount;
} elseif ( $type === 'percentage' ) {
$fee = $subtotal * ( $amount / 100.0 );
} elseif ( $type === 'per_step' ) {
$fee = $groups * $amount;
}
if ( $fee <= 0 ) return;
$charge_label = get_option( 'pacs_label', 'Packaging fee' );
$container_label = get_option( 'pacs_container_label', 'Container' );
$unit_label = get_option( 'pacs_unit_label', 'db' );
$label = $charge_label . ' (' . $groups . ' ' . $unit_label . ' ' . $container_label . ')';
$cart->add_fee( $label, $fee, true );
});
/* Shupping costs multiply by containers */
add_filter( 'woocommerce_package_rates', function( $rates, $package ) {
if ( get_option( 'pacs_enable' ) !== 'yes' ) return $rates;
$groups = pacs_calculate_groups();
foreach ( $rates as $rate_id => $rate ) {
$rates[ $rate_id ]->cost = $rates[ $rate_id ]->cost * $groups;
if ( ! empty( $rates[ $rate_id ]->taxes ) && is_array( $rates[ $rate_id ]->taxes ) ) {
$taxes = $rates[ $rate_id ]->taxes;
foreach ( $taxes as $i => $tax_amount ) {
$taxes[$i] = $tax_amount * $groups;
}
$rates[ $rate_id ]->taxes = $taxes;
}
}
return $rates;
}, 10, 2 );
/* Defaults on activation */
register_activation_hook( __FILE__, function() {
$defaults = array(
'pacs_enable' => 'no',
'pacs_label' => 'Packing fee',
'pacs_amount' => '0',
'pacs_calculation_type' => 'fixed',
'pacs_step' => '1',
'pacs_container_label' => 'Packing container',
'pacs_unit_label' => 'db',
'pacs_counts_per_shipping_class' => 'no',
'pacs_step_none' => '1',
'pacs_allow_mix' => 'yes'
);
foreach ( $defaults as $key => $value ) {
if ( get_option( $key ) === false ) {
update_option( $key, $value );
}
}
if ( function_exists( 'WC' ) && WC()->shipping ) {
$shipping_classes = WC()->shipping->get_shipping_classes();
if ( is_array( $shipping_classes ) ) {
foreach ( $shipping_classes as $class ) {
if ( isset( $class->slug ) ) {
$opt_key = 'pacs_step_' . $class->slug;
if ( get_option( $opt_key ) === false ) {
update_option( $opt_key, '1' );
}
}
}
}
}
});
Viewing 3 replies - 1 through 3 (of 3 total)
Viewing 3 replies - 1 through 3 (of 3 total)
You must be logged in to reply to this topic.