코스모스팜 포인트 결제 for 우커머스, 부가세 적용 문제 (직접 해결했습니다. 다음 업데이트 반영 부탁드립니다.)

1. 정확한 제품 또는 플러그인 이름

코스모스팜 포인트 결제 for 우커머스

 

2. 상세 내용

안녕하세요. 저번에도 문의드렸지만, 마냥 기다리고 있을 수만은 없어서 제가 직접 플러그인 코드를 수정하여 해결했습니다.

과세상품에 포인트 적용 시 부가세 차감이 되지 않아서, 카드 결제 요청 시 카드사에서 거부당하는 문제였는데요.
자세한 내용은 이전 게시글 참고 부탁드립니다.

기존에 caculate_point() 함수가 woocommerce_calculated_total 필터훅에 연결되어 있어서, 주문총액에 포인트를 차감시켜도 부가세는 변동이 없는 문제가 있었습니다.
그리하여 애초에 포인트 적용 시 부가세를 포함한 상품가격 자체가 업데이트되도록 woocommerce_before_calculate_totals 액션훅을 이용하여 문제를 해결했습니다.

장바구니에 여러 개의 상품이 있을 때는 위에서부터 순차적으로 포인트가 적용되도록 했습니다. 적용 포인트 최대금액을 넘지 않도록 했구요.
배송비에는 포인트 적용하지 않고 있어서, 배송비에 대한 처리는 생략했습니다.

다음 업데이트 시 꼭 적용 부탁드립니다.

 

<기존 Cosmosfarm_Point_Pay_WC_Controller.class.php 관련 코드>

<?php
/**
 * Cosmosfarm_Point_Pay_WC_Controller
 * @link https://www.cosmosfarm.com/
 * @copyright Copyright 2023 Cosmosfarm. All rights reserved.
 */
class Cosmosfarm_Point_Pay_WC_Controller {

    // 중간 생략

    add_filter('woocommerce_calculated_total', array($this, 'caculate_point'), 10, 2);

    // 중간 생략

	/**
	 * 포인트 표시 및 금액을 계산한다.
	 */
     public function caculate_point($total, $cart)
	{
		extract(Cosmosfarm_Point_Pay_WC_Point::get_cosmosfarm_point_pay_wc_setting());

		if (!$activation_use) {
			return $total;
		}

		$taxable_total = 0;
		$nontaxable_total = 0;

		foreach ($cart->get_cart() as $item) {
			$point = isset($item['cosmosfarm_pay_apply_point']) ? intval($item['cosmosfarm_pay_apply_point']) : '';

			// 포인트 사용 불가 상품이 있는 경우 계산하지 않는다.
			$product_id = isset($item['variation_id']) && $item['variation_id'] ? intval($item['variation_id']) : intval($item['product_id']);
			$product_use_restrict = get_post_meta($product_id, 'cosmosfarm_point_pay_wc_use_restrict', true);
			if ($product_use_restrict) {
				return $total;
			}

			$tax_status = get_post_meta($product_id, '_tax_status', true);
			if ($tax_status === 'taxable') {
				$taxable_total += $item['line_total'];
			} else {
				$nontaxable_total += $item['line_total'];
			}
		}

		if ($taxable_total > 0) {
			$shipment_fee = $cart->get_shipping_total();
			$tax = $cart->get_tax_totals();
			$tax = $tax["부가가치세-1"]->amount;

			$tax_rate = 0.1;
			$revised_tax = $tax - (intval($point) * $tax_rate);

			$taxable_point = intval($point) * (($taxable_total + $tax + $shipment_fee) / $total);
			$total -= $taxable_point;
		}

		if ($nontaxable_total > 0) {
			$nontaxable_point = intval($point) * ($nontaxable_total / $total);
			$total -= $nontaxable_point;
		}

		return $total;
	}

// 이하 생략

 

 

<수정한 Cosmosfarm_Point_Pay_WC_Controller.class.php 관련 코드>

<?php
/**
 * Cosmosfarm_Point_Pay_WC_Controller
 * @link https://www.cosmosfarm.com/
 * @copyright Copyright 2023 Cosmosfarm. All rights reserved.
 */
class Cosmosfarm_Point_Pay_WC_Controller {

    //중간 생략

    add_action('woocommerce_before_calculate_totals', array($this, 'caculate_point'), 10, 1);

    // 중간 생략

    	public function caculate_point($cart)
	{
		if (is_admin() && !defined('DOING_AJAX')) return;

		extract(Cosmosfarm_Point_Pay_WC_Point::get_cosmosfarm_point_pay_wc_setting());

		if (!$activation_use) {
			return;
		}

		foreach ($cart->get_cart() as $cart_item_key => $item) {
			$point = isset($item['cosmosfarm_pay_apply_point']) ? intval($item['cosmosfarm_pay_apply_point']) : '';
			if ($point == '') return;
		}
		
		$applied_point = 0;
		$remaining_point = $point;
		foreach ($cart->get_cart() as $cart_item_key => $item) {
			if ($applied_point >= $point) break;
			// 포인트 사용 불가 상품이 있는 경우 계산하지 않는다.
			$product_id = isset($item['variation_id']) && $item['variation_id'] ? intval($item['variation_id']) : intval($item['product_id']);
			$product_use_restrict = get_post_meta($product_id, 'cosmosfarm_point_pay_wc_use_restrict', true);
			if ($product_use_restrict) {
				continue;
			}

			$discount_price = $remaining_point;

			if ($discount_price > 0) {
                // 수량이 2개 이상인 경우 
				if ($item['quantity'] >1) {
					$new_price = max(0, floatval($item['data']->get_price()) - (floatval($discount_price)/$item['quantity']));
				} else {
					$new_price = max(0, floatval($item['data']->get_price()) - floatval($discount_price));
				}
				$applied_point += min(floatval($item['data']->get_price()), floatval($discount_price));
				$remaining_point = $point - $applied_point;

				$item['data']->set_price(floatval(number_format((float)$new_price, wc_get_price_decimals(), '.', '')));
			}
		}
	}

// 이하 생략

 

마지막으로 한 가지 남아있는 문제는, 카트의 각 상품에 대하여 적용 가격을 바꾸는 방식이다보니,
한 상품의 수량이 2개 이상일 때 포인트를 1,000원 2,000원 이렇게 딱 맞는 금액으로 적용하지 않고 6,542원 이런 식으로 적용하면 최종금액에 원단위 오차가 발생합니다.

if ($item['quantity'] >1) {
    $new_price = max(0, floatval($item['data']->get_price()) - (floatval($discount_price)/$item['quantity']));
}

이 부분은 제 실력의 한계로 해결하지 못했습니다. 포인트 계산 방식을 아예 바꾸거나 포인트를 100원 단위로 입력하는 등의 조정이 필요해보입니다.

 

좋은 정보와 인맥을 동시에, 워드프레스 사용자 단톡방 참여하기
워드프레스 에러 기술지원 서비스 전문가에게 맡기세요
좋은 정보와 인맥을 동시에, 워드프레스 사용자 단톡방 참여하기