Možná jste se tím již setkali. Chcete zobrazovat cenu produktů na dvě desetiná čísla, ale celkovou cenu na objednávce a faktuře potřebujete mít zaokrouhleno na celé číslo. WooCommerce sice umožňuje nastavit počet desetin, ale globálně pro celý eshop.
Dnešní článek bude obsahovat trochu více kódu, ale ukážeme si, jak upravit zobrazování celkového součtu v košíku, checkoutu a objednávce.
Co potřebujeme upravit
Jak jsem psal výše, chceme zaokrouhlit celkový součet, na celé číslo.
Pokud se podíváme do souboru cart-totals.php ve složce themes, uvidíme, že o výpis součtu, se stará funkce wc_cart_totals_order_total_html().
Tu najdeme v souboru wc-cart-funcitons.php. A zde narážíme na první problém, Funkce neobsahuje žádné filtry, nebo akce. Pokud se ale pdíváme pozorněji, zjistíme, že o zobrazení celkové ceny se stará zápis WC()->cart->get_total() a pokud se má zobrazit i DPH, je načteno do pole $tax_string_array a pak zobrazeno.
V souboru class-wc-cart.php najdeme zmíněnou metodu get_total a můžeme zajásat, protože tam již máme k dispozici filter. Metoda vypadá takto:
public function get_total() {
return apply_filters( 'woocommerce_cart_total', wc_price( $this->total ) );
}
Pokud nevíte, co dělá funkce wc_price(), tak ta se stará o výpis zformátované ceny. Zjišťuje, kolik je desetiných míst nastavených, jaká měna, zkrátka vše, co potřebujete k výpisu ceny v šabloně.
Protože máme k dispozici filter pro cart total, upravíme pouze to co dodává funkce wc_price. Vytvoříme so vlastní funkci, která bude identická, jen se bude lišit v
$num_decimals = absint( get_option( 'woocommerce_price_num_decimals' ) );
$num_decimals = absint( 0 );
Celá funkce:
function custom_wc_price( $price, $args = array() ) {
extract( shortcode_atts( array(
'ex_tax_label' => '0'
), $args ) );
$return = '';
$num_decimals = absint( 0 );
$currency = isset( $args['currency'] ) ? $args['currency'] : '';
$currency_symbol = get_woocommerce_currency_symbol($currency);
$decimal_sep = wp_specialchars_decode( stripslashes( get_option( 'woocommerce_price_decimal_sep' ) ), ENT_QUOTES );
$thousands_sep = wp_specialchars_decode( stripslashes( get_option( 'woocommerce_price_thousand_sep' ) ), ENT_QUOTES );
if ( $price < 0 ) { $price = $price * -1; $negative = true; } else { $negative = false; } $price = apply_filters( 'raw_woocommerce_price', floatval( $price ) ); $price = apply_filters( 'formatted_woocommerce_price', number_format( $price, $num_decimals, $decimal_sep, $thousands_sep ), $price, $num_decimals, $decimal_sep, $thousands_sep ); if ( apply_filters( 'woocommerce_price_trim_zeros', false ) && $num_decimals > 0 ) {
$price = wc_trim_zeros( $price );
}
$formatted_price = ( $negative ? '-' : '' ) . sprintf( get_woocommerce_price_format(), $currency_symbol, $price );
$return = '' . $formatted_price . '';
if ( $ex_tax_label && get_option( 'woocommerce_calc_taxes' ) == 'yes' ) {
$return .= ' ' . WC()->countries->ex_tax_or_vat() . '';
}
return $return;
}
Nyní musíme zaokrouhlenou cenu vložit na příslušné místo pomocí filtru:
add_filter( 'woocommerce_cart_total', 'round_price',999 );
function round_price(){
$rounded = WC()->cart->total;
return custom_wc_price( $rounded );
}
Takže nyní se nám zobrazuje v součtu košíku cena bez desetiných míst, ale pokud máte nastaveno zobrazování DPH, tak tax se ještě zobrazuje nezaokrouhlená.
V souboru class-wc-cart.php najdeme metodu get_tax_totals(), která obsahuje filter woocommerce_cart_tax_totals.
Důležitá je pro nás tato řádka:
$tax_totals[ $code ]->formatted_amount = wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ) );
Protože jsme si již vytvořili ekvivalent funkce wc_price(), zkopírujeme metodu do nové funkce, nahradíme wc_price() a využijeme filter woocommerce_cart_tax_totals, který obsahuje.
add_filter( 'woocommerce_cart_tax_totals', 'round_cart_tax_totals',999 );
function round_cart_tax_totals(){
$taxes = WC()->cart->get_taxes();
$tax_totals = array();
foreach ( $taxes as $key => $tax ) {
$code = WC()->cart->tax->get_rate_code( $key );
if ( $code ) {
if ( ! isset( $tax_totals[ $code ] ) ) {
$tax_totals[ $code ] = new stdClass();
$tax_totals[ $code ]->amount = 0;
}
$tax_totals[ $code ]->tax_rate_id = $key;
$tax_totals[ $code ]->is_compound = WC()->cart->tax->is_compound( $key );
$tax_totals[ $code ]->label = WC()->cart->tax->get_rate_label( $key );
$tax_totals[ $code ]->amount += wc_round_tax_total( $tax );
$tax_totals[ $code ]->formatted_amount = $this->custom_wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ) );
}
}
return $tax_totals;
}
Tím jsme dosáhli požadovaného výsledku pro zobrazení součtu v košíku a na stránce pokladny. Musíme však ještě vytvořit obdobné úpravy i pro thankyou stránku, pro detail objednávky ve vašem účtu a detailu objednávky v administraci.
Pokud se podíváte do thankyou.php ve složce templates/checkout, uvidíte, že o zobrazení se stará $order->get_formatted_order_total().
Najdeme ve složce includes/abstract/anstract-wc-order.php a v souboru metodu get_formatted_order_total().
Ta vypadá takto:
public function get_formatted_order_total() {
$formatted_total = wc_price( $this->get_total(), array( 'currency' => $this->get_order_currency() ) );
return apply_filters( 'woocommerce_get_formatted_order_total', $formatted_total, $this );
}
Díky filtru woocommerce_get_formatted_order_total a naší custom_wc_price() upravíme celkový součet:
add_filter( 'woocommerce_get_formatted_order_total', 'custom_get_formatted_order_total',999, 2 );
function custom_get_formatted_order_total($formatted_total, $order) {
$formatted_total = custom_wc_price( $order->get_total(), array( 'currency' => $order->get_order_currency() ) );
return $formatted_total;
}
A máme před sebou poslední krok. Najdeme si v templates/order/order-details.php, kde najdeme:
if ( $totals = $order->get_order_item_totals() ) foreach ( $totals as $total ) :
?>
<?php endforeach;
Opět se podíváme do abstract-wc-order.php na metodu get_order_item_totals(). V metodě se prochází pole $total_rows, ale nás zajímá pouze to s klíčem order_total. Jeho hodnota vypadá takto:
$total_rows['order_total'] = array(
'label' => __( 'Order Total:', 'woocommerce' ),
'value' => $this->get_formatted_order_total()
);
A protože obsahuje i filter woocommerce_get_order_item_totals, pomocí něj upravíme i hodnotu pole.
add_filter( 'woocommerce_get_order_item_totals', 'custom_get_order_item_totals',999, 2 );
function custom_get_order_item_totals($total_rows, $order){
$total_rows['order_total'] = array();
$total_rows['order_total']['label'] = __( 'Total:', 'woocommerce' );
$total_rows['order_total']['value'] = $order->get_formatted_order_total();
$tax_string_array = array();
if ( 'itemized' == get_option( 'woocommerce_tax_total_display' ) ) {
foreach ( $order->get_tax_totals() as $code => $tax ) {
$tax_string_array[] = sprintf( '%s %s', $tax->formatted_amount, $tax->label );
}
} else {
$tax_string_array[] = sprintf( '%s %s', $this->custom_wc_price( $order->get_total_tax(), array('currency' => $order->get_order_currency()) ), WC()->countries->tax_or_vat() );
}
if ( ! empty( $tax_string_array ) ) {
$total_rows['order_total']['value'] .= ' ' . sprintf( __( '(Includes %s)', 'woocommerce' ), implode( ', ', $tax_string_array ) );
}
return $total_rows;
}
Tím jsme upravili celkový součet a úpravou $order->get_total_tax(), pomocí filtru woocommerce_order_tax_totals zaokrouhlíme částku za DPH.
add_filter( 'woocommerce_order_tax_totals', 'custom_round_order_tax_totals',999, 2 );
custom_round_order_tax_totals($tax_totals, $order){
$taxes = $order->get_items( 'tax' );
$tax_totals = array();
foreach ( $taxes as $key => $tax ) {
$code = $tax[ 'name' ];
if ( ! isset( $tax_totals[ $code ] ) ) {
$tax_totals[ $code ] = new stdClass();
$tax_totals[ $code ]->amount = 0;
}
$tax_totals[ $code ]->id = $key;
$tax_totals[ $code ]->rate_id = $tax['rate_id'];
$tax_totals[ $code ]->is_compound = $tax[ 'compound' ];
$tax_totals[ $code ]->label = isset( $tax[ 'label' ] ) ? $tax[ 'label' ] : $tax[ 'name' ];
$tax_totals[ $code ]->amount += $tax[ 'tax_amount' ] + $tax[ 'shipping_tax_amount' ];
$tax_totals[ $code ]->formatted_amount = custom_wc_price( wc_round_tax_total( $tax_totals[ $code ]->amount ), array('currency' => $order->get_order_currency()) );
}
return $tax_totals;
}
Jak můžete vidět, opět jsme použili funkci custom_wc_price. Úpravy, které ovlivní zobrazování celkového součtu v objednávce na front endu, upraví i zobrazení celkové ceny v administraci objednávky.
Těším se u dalšího návodu.