JezK
Edit File: Calculator.php
<?php namespace WeDevs\Dokan\Commission; use Automattic\WooCommerce\Utilities\NumberUtil; use WeDevs\Dokan\Commission\AbstractCommissionCalculator; use WeDevs\Dokan\Commission\Model\Commission; use WeDevs\Dokan\Commission\Model\Setting; class Calculator extends AbstractCommissionCalculator { protected float $subtotal = 0.0; protected float $total = 0.0; protected int $quantity = 0; protected Setting $settings; protected ?CouponInfo $discount; /** * @return float */ public function get_subtotal(): float { return $this->subtotal; } /** * @param float $subtotal * * @return Calculator */ public function set_subtotal( float $subtotal ): Calculator { $this->subtotal = $subtotal; return $this; } /** * @return float */ public function get_total(): float { return $this->total; } /** * @param float $total * * @return Calculator */ public function set_total( float $total ): Calculator { $this->total = $total; return $this; } /** * @return int */ public function get_quantity(): int { return $this->quantity; } /** * @param int $quantity * * @return Calculator */ public function set_quantity( int $quantity ): Calculator { $this->quantity = $quantity; return $this; } /** * @return Setting */ public function get_settings(): Setting { return $this->settings; } /** * @param Setting $settings * * @return Calculator */ public function set_settings( Setting $settings ): Calculator { $this->settings = $settings; return $this; } /** * @return mixed */ public function get_discount(): CouponInfo { return $this->discount ?? new CouponInfo( [] ); } /** * @param CouponInfo $discount * * @return Calculator */ public function set_discount( CouponInfo $discount ): Calculator { $this->discount = $discount; return $this; } /** * Calculates the commission based on discounts and settings. * * @return Commission */ public function calculate(): Commission { $raw_admin_commission = $this->calculate_raw_admin_commission(); // Round only the admin's share and let the vendor take the exact remainder. // Rounding both shares leaves a fraction of a cent credited to neither party. $net_amount = $this->get_total(); $admin_commission = min( NumberUtil::round( $raw_admin_commission, wc_get_price_decimals() ), $net_amount ); $vendor_earning = $net_amount - $admin_commission; return $this->create_commission( $admin_commission, $vendor_earning, ); } /** * Calculates the raw admin commission before capping. * * @param float $net_amount_with_admin_discount Amount after vendor discount. * @param float $vendor_discount Discount given by vendor. * @param float $admin_discount Discount given by admin. * @return float */ private function calculate_raw_admin_commission(): float { $admin_discount = $this->get_discount()->get_admin_discount(); $net_amount_with_admin_discount = $this->get_total() + $admin_discount; $percentage_commission = ( $net_amount_with_admin_discount * $this->settings->get_percentage_value() ) / 100; $flat_commission = $this->settings->get_flat_value() * $this->quantity; $combine_flat = $this->settings->get_combine_flat(); return $percentage_commission + $flat_commission + $combine_flat - $admin_discount; } /** * Creates the commission object with all related values. * * @param float $admin_commission Final admin commission. * @param float $vendor_discount Vendor's discount. * @param float $vendor_earning Vendor's earning. * @param float $admin_discount Admin's discount. * @return Commission */ private function create_commission( float $admin_commission, float $vendor_earning ): Commission { $commission = new Commission(); $commission->set_admin_net_commission( $admin_commission ); $commission->set_vendor_discount( $this->get_discount()->get_vendor_discount() ); $commission->set_vendor_net_earning( $vendor_earning ); $commission->set_admin_discount( $this->get_discount()->get_admin_discount() ); $commission->set_settings( $this->settings ); return $commission; } /** * @inheritDoc */ public function get(): Commission { return $this->calculate(); } /** * Calculate vendor and admin earnings after a refund. * * @param float $vendor_earning Original vendor earning. * @param float $admin_commission Original admin commission. * @param float $item_total Original item total (excluding tax/shipping). * @param float $refund_amount Refunded amount for the item. * * @return Commission */ public function calculate_for_refund( float $vendor_earning, float $admin_commission, float $item_total, float $refund_amount ): Commission { $commission = new Commission(); if ( $item_total === floatval( 0 ) ) { $commission->set_admin_net_commission( 0 ); $commission->set_vendor_net_earning( 0 ); return $commission; } $refund_amount = abs( $refund_amount ); // Split the refund the same way calculate() splits a sale, so the amounts // refunded always add back up to the amount taken off the order. $admin_commission_for_refund = NumberUtil::round( ( $admin_commission / $item_total ) * $refund_amount, wc_get_price_decimals() ); $vendor_earning_for_refund = $refund_amount - $admin_commission_for_refund; $commission->set_vendor_net_earning( $vendor_earning_for_refund ); $commission->set_admin_net_commission( $admin_commission_for_refund ); return $commission; } }