diff --git a/assets/src/js/withdraw.js b/assets/src/js/withdraw.js
index 9835b7a01c..f7ddf676f9 100644
--- a/assets/src/js/withdraw.js
+++ b/assets/src/js/withdraw.js
@@ -26,6 +26,28 @@
$("input[name='withdraw-schedule']").on( 'change', (e) => {
Dokan_Withdraw.handleScheduleChange( e );
});
+
+ $( "[name='withdraw_method'][id='withdraw-method']" ).on( 'change', ( e ) => {
+ Dokan_Withdraw.calculateWithdrawCharges();
+ } );
+
+ $( 'input#withdraw-amount' ).on( 'keyup', Dokan_Withdraw.debounce( Dokan_Withdraw.calculateWithdrawCharges, 500 ) );
+ },
+
+ debounce( func, wait, immediate ) {
+ var timeout;
+ return function () {
+ var context = this,
+ args = arguments;
+ var later = function () {
+ timeout = null;
+ if ( ! immediate ) func.apply( context, args );
+ };
+ var callNow = immediate && ! timeout;
+ clearTimeout( timeout );
+ timeout = setTimeout( later, wait );
+ if ( callNow ) func.apply( context, args );
+ };
},
openRequestWithdrawWindow: () => {
const withdrawTemplate = wp.template( 'withdraw-request-popup' ),
@@ -33,6 +55,9 @@
width : 690,
overlayColor: 'rgba(0, 0, 0, 0.8)',
headerColor : dokan.modal_header_color,
+ onOpening : function ( modal ) {
+ Dokan_Withdraw.calculateWithdrawCharges();
+ },
} );
modal.iziModal( 'setContent', withdrawTemplate().trim() );
@@ -200,6 +225,75 @@
const nextDate = $(e.target).data('next-schedule');
$( '#dokan-withdraw-next-scheduled-date').html(nextDate);
},
+ calculateWithdrawCharges: () => {
+ let charges = $( "select[name='withdraw_method'][id='withdraw-method'] option:selected" ).data();
+ if (
+ $( '#dokan-send-withdraw-request-popup-form > .dokan-alert-danger' ).length
+ || ! charges
+ ) {
+ return;
+ }
+
+ let withdrawMethod = $( "[name='withdraw_method'][id='withdraw-method']" ).val();
+ let withdrawAmount = $( "[name='withdraw_amount'][id='withdraw-amount']" ).val();
+
+ withdrawAmount = accounting.unformat(
+ withdrawAmount,
+ dokan.mon_decimal_point
+ );
+ let { chargePercentage, chargeFixed } = $(
+ "select[name='withdraw_method'][id='withdraw-method'] option:selected"
+ ).data();
+ let chargeAmount = 0;
+ let chargeText = '';
+
+ if ( chargeFixed ) {
+ chargeText += Dokan_Withdraw.formatMoney( chargeFixed );
+ chargeAmount += chargeFixed;
+ }
+ if ( chargePercentage ) {
+ let percentageAmount = chargePercentage / 100 * withdrawAmount;
+ chargeAmount += percentageAmount;
+ chargeText += chargeText ? ' + ' : '';
+ chargeText += parseFloat( accounting.formatNumber( chargePercentage, dokan.rounding_precision, '' ) )
+ .toString()
+ .replace('.', dokan.mon_decimal_point ) + '%';
+ chargeText += ` = ${ Dokan_Withdraw.formatMoney( chargeAmount ) }`;
+ }
+
+ if ( ! chargeText ) {
+ chargeText = Dokan_Withdraw.formatMoney( chargeAmount, dokan.currency );
+ }
+
+ Dokan_Withdraw.showWithdrawChargeHtml( chargeText, chargeAmount, withdrawAmount );
+ },
+
+ formatMoney( money ) {
+ return accounting.formatMoney( money, {
+ symbol: dokan.currency_format_symbol,
+ decimal: dokan.currency_format_decimal_sep,
+ thousand: dokan.currency_format_thousand_sep,
+ precision: dokan.currency_format_num_decimals,
+ format: dokan.currency_format
+ } )
+ },
+
+ showWithdrawChargeHtml(chargeText, chargeAmount, withdrawAmount) {
+ let chargeSection = $('#dokan-withdraw-charge-section');
+ let revivableSection = $('#dokan-withdraw-revivable-section');
+
+ if (!withdrawAmount) {
+ chargeSection.hide();
+ revivableSection.hide();
+ return;
+ }
+
+ $('#dokan-withdraw-charge-section-text').html(chargeText);
+ $('#dokan-withdraw-revivable-section-text').html(Dokan_Withdraw.formatMoney(withdrawAmount - chargeAmount));
+
+ chargeSection.show();
+ revivableSection.show();
+ }
};
$(document).ready(function() {
diff --git a/dokan.php b/dokan.php
index ff08ce1aa6..d2ad3c1b5d 100755
--- a/dokan.php
+++ b/dokan.php
@@ -54,6 +54,7 @@
* @property WeDevs\Dokan\Product\Manager $product Instance of Order Manager class
* @property WeDevs\Dokan\Vendor\Manager $vendor Instance of Vendor Manager Class
* @property WeDevs\Dokan\BackgroundProcess\Manager $bg_process Instance of WeDevs\Dokan\BackgroundProcess\Manager class
+ * @property WeDevs\Dokan\Withdraw\Manager $withdraw Instance of WeDevs\Dokan\Withdraw\Manager class
* @property WeDevs\Dokan\Frontend\Frontend $frontend_manager Instance of \WeDevs\Dokan\Frontend\Frontend class
*/
final class WeDevs_Dokan {
@@ -584,7 +585,7 @@ public function get_db_version_key() {
*
* @return WeDevs_Dokan
*/
-function dokan() {
+function dokan() { // phpcs:ignore
return WeDevs_Dokan::init();
}
diff --git a/includes/Admin/Settings.php b/includes/Admin/Settings.php
index bf19079aea..fcaba5c1cd 100644
--- a/includes/Admin/Settings.php
+++ b/includes/Admin/Settings.php
@@ -319,7 +319,7 @@ public function get_settings_sections() {
'description' => __( 'Withdraw Settings, Threshold', 'dokan-lite' ),
'document_link' => 'https://wedevs.com/docs/dokan/settings/withdraw-options/',
'settings_title' => __( 'Withdraw Settings', 'dokan-lite' ),
- 'settings_description' => __( 'You can configure your store\'s withdrawal methods, limits, order status and more.', 'dokan-lite' ),
+ 'settings_description' => __( 'You can configure your store\'s withdrawal methods, charges, limits, order status and more.', 'dokan-lite' ),
],
[
'id' => 'dokan_reverse_withdrawal',
@@ -617,6 +617,24 @@ public function get_settings_fields() {
'options' => dokan_withdraw_get_methods(),
'tooltip' => __( 'Check to add available payment methods for vendors to withdraw money.', 'dokan-lite' ),
],
+ 'withdraw_charges' => [
+ 'name' => 'withdraw_charges',
+ 'label' => __( 'Withdraw Charges', 'dokan-lite' ),
+ 'desc' => __( 'Select suitable withdraw charges for vendors', 'dokan-lite' ),
+ 'type' => 'charges',
+ 'options' => dokan_withdraw_get_methods(),
+ 'chargeable_methods' => dokan_withdraw_get_chargeable_methods(),
+ 'default' => dokan_withdraw_get_method_charges(),
+ 'show_if' => [
+ 'withdraw_methods' => [
+ 'contains-any' => array_keys( dokan_withdraw_get_methods() ),
+ ],
+ ],
+ 'items_show_if' => [
+ 'key' => 'withdraw_methods',
+ 'condition' => 'contains-key-value',
+ ],
+ ],
'withdraw_limit' => [
'name' => 'withdraw_limit',
'label' => __( 'Minimum Withdraw Limit', 'dokan-lite' ),
diff --git a/includes/Assets.php b/includes/Assets.php
index db566c4305..f6842b1690 100644
--- a/includes/Assets.php
+++ b/includes/Assets.php
@@ -478,7 +478,7 @@ public function get_scripts() {
],
'dokan-script' => [
'src' => $asset_url . '/js/dokan.js',
- 'deps' => [ 'imgareaselect', 'customize-base', 'customize-model', 'dokan-i18n-jed', 'jquery-tiptip', 'moment', 'dokan-date-range-picker' ],
+ 'deps' => [ 'imgareaselect', 'customize-base', 'customize-model', 'dokan-i18n-jed', 'jquery-tiptip', 'moment', 'dokan-date-range-picker', 'dokan-accounting' ],
'version' => filemtime( $asset_path . 'js/dokan.js' ),
],
'dokan-vue-vendor' => [
@@ -576,24 +576,30 @@ public function enqueue_front_scripts() {
}
$default_script = [
- 'ajaxurl' => admin_url( 'admin-ajax.php' ),
- 'nonce' => wp_create_nonce( 'dokan_reviews' ),
- 'ajax_loader' => DOKAN_PLUGIN_ASSEST . '/images/ajax-loader.gif',
- 'seller' => [
+ 'ajaxurl' => admin_url( 'admin-ajax.php' ),
+ 'nonce' => wp_create_nonce( 'dokan_reviews' ),
+ 'ajax_loader' => DOKAN_PLUGIN_ASSEST . '/images/ajax-loader.gif',
+ 'seller' => [
'available' => __( 'Available', 'dokan-lite' ),
'notAvailable' => __( 'Not Available', 'dokan-lite' ),
],
- 'delete_confirm' => __( 'Are you sure?', 'dokan-lite' ),
- 'wrong_message' => __( 'Something went wrong. Please try again.', 'dokan-lite' ),
- 'vendor_percentage' => dokan_get_seller_percentage( dokan_get_current_user_id() ),
- 'commission_type' => dokan_get_commission_type( dokan_get_current_user_id() ),
- 'rounding_precision' => wc_get_rounding_precision(),
- 'mon_decimal_point' => wc_get_price_decimal_separator(),
- 'product_types' => apply_filters( 'dokan_product_types', [ 'simple' ] ),
- 'loading_img' => DOKAN_PLUGIN_ASSEST . '/images/loading.gif',
- 'store_product_search_nonce' => wp_create_nonce( 'dokan_store_product_search_nonce' ),
- 'i18n_download_permission' => __( 'Are you sure you want to revoke access to this download?', 'dokan-lite' ),
- 'i18n_download_access' => __( 'Could not grant access - the user may already have permission for this file or billing email is not set. Ensure the billing email is set, and the order has been saved.', 'dokan-lite' ),
+ 'delete_confirm' => __( 'Are you sure?', 'dokan-lite' ),
+ 'wrong_message' => __( 'Something went wrong. Please try again.', 'dokan-lite' ),
+ 'vendor_percentage' => dokan_get_seller_percentage( dokan_get_current_user_id() ),
+ 'commission_type' => dokan_get_commission_type( dokan_get_current_user_id() ),
+ 'rounding_precision' => wc_get_rounding_precision(),
+ 'mon_decimal_point' => wc_get_price_decimal_separator(),
+ 'currency_format_num_decimals' => wc_get_price_decimals(),
+ 'currency_format_symbol' => get_woocommerce_currency_symbol(),
+ 'currency_format_decimal_sep' => esc_attr( wc_get_price_decimal_separator() ),
+ 'currency_format_thousand_sep' => esc_attr( wc_get_price_thousand_separator() ),
+ 'currency_format' => esc_attr( str_replace( [ '%1$s', '%2$s' ], [ '%s', '%v' ], get_woocommerce_price_format() ) ), // For accounting JS
+ 'round_at_subtotal' => get_option( 'woocommerce_tax_round_at_subtotal', 'no' ),
+ 'product_types' => apply_filters( 'dokan_product_types', [ 'simple' ] ),
+ 'loading_img' => DOKAN_PLUGIN_ASSEST . '/images/loading.gif',
+ 'store_product_search_nonce' => wp_create_nonce( 'dokan_store_product_search_nonce' ),
+ 'i18n_download_permission' => __( 'Are you sure you want to revoke access to this download?', 'dokan-lite' ),
+ 'i18n_download_access' => __( 'Could not grant access - the user may already have permission for this file or billing email is not set. Ensure the billing email is set, and the order has been saved.', 'dokan-lite' ),
/**
* Filter of maximun a vendor can add tags.
*
diff --git a/includes/Dashboard/Templates/Withdraw.php b/includes/Dashboard/Templates/Withdraw.php
index 0664237822..13347a54fb 100755
--- a/includes/Dashboard/Templates/Withdraw.php
+++ b/includes/Dashboard/Templates/Withdraw.php
@@ -434,13 +434,16 @@ public function withdraw_dashboard_layout_display() {
return;
}
+ /**
+ * @var $last_withdraw \WeDevs\Dokan\Withdraw\Withdraw[]
+ */
$last_withdraw = dokan()->withdraw->get_withdraw_requests( dokan_get_current_user_id(), 1, 1 );
$payment_details = __( 'You do not have any approved withdraw yet.', 'dokan-lite' );
if ( ! empty( $last_withdraw ) ) {
- $last_withdraw_amount = '' . wc_price( $last_withdraw[0]->amount ) . '';
- $last_withdraw_date = '' . dokan_format_date( $last_withdraw[0]->date ) . '';
- $last_withdraw_method_used = '' . dokan_withdraw_get_method_title( $last_withdraw[0]->method ) . '';
+ $last_withdraw_amount = '' . wc_price( $last_withdraw[0]->get_amount() ) . '';
+ $last_withdraw_date = '' . dokan_format_date( $last_withdraw[0]->get_date() ) . '';
+ $last_withdraw_method_used = '' . dokan_withdraw_get_method_title( $last_withdraw[0]->get_method() ) . '';
// translators: 1: Last formatted withdraw amount 2: Last formatted withdraw date 3: Last formatted withdraw method used.
$payment_details = sprintf( __( '%1$s on %2$s to %3$s', 'dokan-lite' ), $last_withdraw_amount, $last_withdraw_date, $last_withdraw_method_used );
@@ -502,9 +505,10 @@ public function withdraw_request_popup_form_content() {
$default_withdraw_method = dokan_withdraw_get_default_method( $current_user_id );
dokan_get_template_part(
'withdraw/request-form', '', array(
- 'amount' => NumberUtil::round( $balance, wc_get_price_decimals(), PHP_ROUND_HALF_DOWN ), // we are setting 12.3456 to 12.34 not 12.35
- 'withdraw_method' => $default_withdraw_method,
- 'payment_methods' => $payment_methods,
+ 'amount' => NumberUtil::round( $balance, wc_get_price_decimals(), PHP_ROUND_HALF_DOWN ), // we are setting 12.3456 to 12.34 not 12.35
+ 'withdraw_method' => $default_withdraw_method,
+ 'payment_methods' => $payment_methods,
+ 'withdraw_charges' => dokan_withdraw_get_method_charges(),
)
);
}
diff --git a/includes/REST/WithdrawController.php b/includes/REST/WithdrawController.php
index 171a9a59ad..36a22a2455 100644
--- a/includes/REST/WithdrawController.php
+++ b/includes/REST/WithdrawController.php
@@ -5,6 +5,7 @@
use Cassandra\Date;
use Exception;
use WeDevs\Dokan\Cache;
+use WeDevs\Dokan\Withdraw\Withdraw;
use WP_Error;
use WP_REST_Controller;
use WP_REST_Request;
@@ -134,6 +135,43 @@ public function register_routes() {
'schema' => [ $this, 'get_public_batch_schema' ],
]
);
+
+ register_rest_route(
+ $this->namespace, '/' . $this->rest_base . '/charges', [
+ [
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => [ $this, 'get_all_method_charges' ],
+ 'permission_callback' => [ $this, 'get_items_permissions_check' ],
+ ],
+ ]
+ );
+
+ $methods = array_keys( dokan_withdraw_get_methods() );
+
+ register_rest_route(
+ $this->namespace, '/' . $this->rest_base . '/charge', [
+ [
+ 'methods' => WP_REST_Server::READABLE,
+ 'callback' => [ $this, 'get_method_charge' ],
+ 'permission_callback' => [ $this, 'get_items_permissions_check' ],
+ 'args' => [
+ 'method' => [
+ 'description' => __( 'Withdraw method key', 'dokan-lite' ),
+ 'type' => 'string',
+ 'context' => [ 'view' ],
+ 'enum' => $methods,
+ 'required' => true,
+ ],
+ 'amount' => [
+ 'description' => __( 'Withdraw amount', 'dokan-lite' ),
+ 'type' => 'number',
+ 'context' => [ 'view' ],
+ 'required' => true,
+ ],
+ ],
+ ],
+ ]
+ );
}
/**
@@ -417,32 +455,40 @@ public function create_item( $request ) {
throw new DokanException( 'dokan_rest_withdraw_error', __( 'No vendor found', 'dokan-lite' ), 404 );
}
- $args = [
- 'user_id' => $user_id,
- 'amount' => $request['amount'],
- 'date' => current_time( 'mysql' ),
- 'method' => $request['method'],
- 'note' => $note,
- 'ip' => dokan_get_client_ip(),
- ];
-
if ( dokan()->withdraw->has_pending_request( $user_id ) ) {
throw new DokanException( 'dokan_rest_withdraw_error', __( 'You already have a pending withdraw request', 'dokan-lite' ), 400 );
}
- $validate_request = dokan()->withdraw->is_valid_approval_request( $args );
+ $validate_request = dokan()->withdraw->is_valid_approval_request(
+ [
+ 'user_id' => $user_id,
+ 'amount' => $request['amount'],
+ 'method' => $request['method'],
+ ]
+ );
if ( is_wp_error( $validate_request ) ) {
throw new DokanException( 'dokan_rest_withdraw_error', $validate_request->get_error_message(), 400 );
}
- $withdraw = dokan()->withdraw->create( $args );
+ $withdraw = new Withdraw();
- if ( is_wp_error( $withdraw ) ) {
- throw new DokanException( $withdraw->get_error_code(), $withdraw->get_error_message(), 400 );
+ $withdraw
+ ->set_user_id( $user_id )
+ ->set_amount( $request['amount'] )
+ ->set_date( dokan_current_datetime()->format( 'Y-m-d H:i:s' ) )
+ ->set_status( dokan()->withdraw->get_status_code( 'pending' ) )
+ ->set_method( $request['method'] )
+ ->set_ip( dokan_get_client_ip() )
+ ->set_note( $note );
+
+ $result = $withdraw->save();
+
+ if ( is_wp_error( $result ) ) {
+ throw new DokanException( $result->get_error_code(), $result->get_error_message(), 400 );
}
- $response = $this->prepare_item_for_response( $withdraw, $request );
+ $response = $this->prepare_item_for_response( $result, $request );
$response = rest_ensure_response( $response );
$response->set_status( 201 );
@@ -702,11 +748,61 @@ public function batch_items( $request ) {
);
}
+ /**
+ * Get all withdraw method charges.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @return WP_Error|\WP_HTTP_Response|WP_REST_Response
+ */
+ public function get_all_method_charges() {
+ $all_charges = dokan_withdraw_get_method_charges();
+
+ return rest_ensure_response( $all_charges );
+ }
+
+ /**
+ * Get withdraw method charge.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @return WP_Error|\WP_HTTP_Response|WP_REST_Response
+ */
+ public function get_method_charge( $request ) {
+ $method = $request->get_param( 'method' );
+ $amount = wc_format_decimal( $request->get_param( 'amount' ) );
+
+ $withdraw = new Withdraw();
+
+ $withdraw->set_method( $method )
+ ->set_amount( $amount )
+ ->calculate_charge();
+
+ $response = [
+ 'charge' => $withdraw->get_charge(),
+ 'receivable' => $withdraw->get_receivable_amount(),
+ 'charge_data' => $withdraw->get_charge_data(),
+ ];
+
+ if ( $withdraw->get_receivable_amount() < 0 ) {
+ return new WP_Error(
+ 'invalid-withdraw-amount',
+ __( 'Invalid withdraw amount. The withdraw charge is greater than the withdraw amount', 'dokan-lite' ),
+ $response
+ );
+ }
+
+ return rest_ensure_response( $response );
+ }
+
/**
* Prepare data for response
*
* @since 2.8.0
*
+ * @param $withdraw \WeDevs\Dokan\Withdraw\Withdraw
+ * @param $request \WP_REST_Request
+ *
* @return WP_REST_Response|WP_Error
*/
public function prepare_item_for_response( $withdraw, $request ) {
@@ -735,6 +831,9 @@ public function prepare_item_for_response( $withdraw, $request ) {
'note' => $withdraw->get_note(),
'details' => $details,
'ip' => $withdraw->get_ip(),
+ 'charge' => $withdraw->get_charge(),
+ 'receivable' => $withdraw->get_receivable_amount(),
+ 'charge_data' => $withdraw->get_charge_data(),
];
$response = rest_ensure_response( $data );
diff --git a/includes/Withdraw/Hooks.php b/includes/Withdraw/Hooks.php
index 5d7dd09637..23acb51a9c 100644
--- a/includes/Withdraw/Hooks.php
+++ b/includes/Withdraw/Hooks.php
@@ -56,7 +56,7 @@ public function download_withdraw_log_export_file() {
*
* @param string $title
* @param string $method_key
- * @param object|null $request
+ * @param Withdraw $request
*
* @return string
*/
@@ -67,8 +67,8 @@ public function dokan_withdraw_dokan_custom_method_title( $title, $method_key, $
if ( empty( $title ) ) {
$title = __( 'Custom', 'dokan-lite' );
}
- if ( null !== $request ) {
- $details = maybe_unserialize( $request->details );
+ if ( null !== $request && null !== $request->get_details() ) {
+ $details = maybe_unserialize( $request->get_details() );
if ( isset( $details['value'] ) ) {
$title .= ' - ' . $details['value'];
}
@@ -184,19 +184,21 @@ public function ajax_handle_withdraw_request() {
wp_send_json_error( $validate_request->get_error_message(), $validate_request->get_error_code() );
}
- $data = [
- 'user_id' => $user_id,
- 'amount' => $amount,
- 'status' => dokan()->withdraw->get_status_code( 'pending' ),
- 'method' => $method,
- 'ip' => dokan_get_client_ip(),
- 'note' => '',
- ];
+ $withdraw = new Withdraw();
+
+ $withdraw
+ ->set_user_id( $user_id )
+ ->set_amount( $amount )
+ ->set_date( dokan_current_datetime()->format( 'Y-m-d H:i:s' ) )
+ ->set_status( dokan()->withdraw->get_status_code( 'pending' ) )
+ ->set_method( $method )
+ ->set_ip( dokan_get_client_ip() )
+ ->set_note( '' );
- $withdraw = dokan()->withdraw->create( $data );
+ $result = $withdraw->save();
- if ( is_wp_error( $withdraw ) ) {
- wp_send_json_error( $withdraw->get_error_message(), $withdraw->get_error_code() );
+ if ( is_wp_error( $result ) ) {
+ wp_send_json_error( $result->get_error_message(), $result->get_error_code() );
}
do_action( 'dokan_after_withdraw_request', $user_id, $amount, $method );
diff --git a/includes/Withdraw/Manager.php b/includes/Withdraw/Manager.php
index 55ab2f5dac..0d87f8cc14 100644
--- a/includes/Withdraw/Manager.php
+++ b/includes/Withdraw/Manager.php
@@ -27,12 +27,16 @@ class Manager {
* @return bool|\WP_Error
*/
public function is_valid_approval_request( $args ) {
+ $withdraw = new Withdraw();
$user_id = $args['user_id'];
$limit = $this->get_withdraw_limit();
$balance = wc_format_decimal( dokan_get_seller_balance( $user_id, false ), 2 );
$amount = wc_format_decimal( $args['amount'], 2 );
$method = $args['method'];
+ $all_withdraw_charges = dokan_withdraw_get_method_charges();
+ $charge_data = $all_withdraw_charges[ $method ];
+
if ( empty( $amount ) ) {
return new WP_Error( 'dokan_withdraw_empty', __( 'Withdraw amount required ', 'dokan-lite' ) );
}
@@ -58,6 +62,18 @@ public function is_valid_approval_request( $args ) {
return new WP_Error( 'dokan_withdraw_already_approved', __( 'Withdraw is already approved.', 'dokan-lite' ) );
}
+ $withdraw
+ ->set_user_id( $user_id )
+ ->set_amount( $amount )
+ ->set_method( $method )
+ ->set_charge_data( $charge_data )
+ ->calculate_charge();
+
+ // Check if withdraw amount is equal or greater than the charge.
+ if ( $withdraw->get_receivable_amount() < 0 ) {
+ return new WP_Error( 'dokan_withdraw_not_enough_balance', __( 'Withdraw amount is less then the withdraw charge.', 'dokan-lite' ) );
+ }
+
/**
* Filter validated withdraw request
*
@@ -227,9 +243,9 @@ public function has_pending_request( $user_id ) {
* @param integer $limit
* @param integer $offset
*
- * @return array
+ * @return Withdraw[]
*/
- public function get_withdraw_requests( $user_id = '', $status = 0, $limit = 10, $offset = 0 ) {
+ public function get_withdraw_requests( $user_id = '', $status = 0, $limit = 10, $offset = 0 ): array {
// get all function arguments as key => value pairs
$args = get_defined_vars();
@@ -245,6 +261,12 @@ public function get_withdraw_requests( $user_id = '', $status = 0, $limit = 10,
$result = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$wpdb->dokan_withdraw} WHERE user_id = %d AND status = %d ORDER BY id DESC LIMIT %d, %d", $user_id, $status, $offset, $limit ) );
}
+ $result = array_map(
+ function ( $withdraw ) {
+ return new Withdraw( $withdraw );
+ }, $result
+ );
+
Cache::set( $cache_key, $result, $cache_group );
}
diff --git a/includes/Withdraw/Withdraw.php b/includes/Withdraw/Withdraw.php
index 38b76f70bb..813144018a 100644
--- a/includes/Withdraw/Withdraw.php
+++ b/includes/Withdraw/Withdraw.php
@@ -22,15 +22,18 @@ class Withdraw {
*/
public function __construct( $data = [] ) {
$defaults = [
- 'id' => 0,
- 'user_id' => 0,
- 'amount' => 0,
- 'date' => current_time( 'mysql' ),
- 'status' => dokan()->withdraw->get_status_code( 'pending' ),
- 'method' => 'paypal',
- 'note' => '',
- 'details' => '',
- 'ip' => '',
+ 'id' => 0,
+ 'user_id' => 0,
+ 'amount' => 0,
+ 'date' => dokan_current_datetime(),
+ 'status' => dokan()->withdraw->get_status_code( 'pending' ),
+ 'method' => 'paypal',
+ 'note' => '',
+ 'details' => '',
+ 'charge' => 0,
+ 'recivable' => 0,
+ 'charge_data' => [],
+ 'ip' => '',
];
$data = wp_parse_args( $data, $defaults );
@@ -46,6 +49,16 @@ public function __construct( $data = [] ) {
'details' => $data['details'],
'ip' => $data['ip'],
];
+
+ $details = maybe_unserialize( $data['details'] );
+ $charge = isset( $details['charge'] ) ? wc_format_decimal( $details['charge'] ) : 0;
+ $receivable = isset( $details['receivable'] ) ? wc_format_decimal( $details['receivable'] ) : $this->get_amount();
+ $charge_data = isset( $details['charge_data'] ) ? $details['charge_data'] : [];
+
+ $this
+ ->set_charge( $charge )
+ ->set_recivable( $receivable )
+ ->set_charge_data( $charge_data );
}
/**
@@ -67,7 +80,7 @@ public function get_withdraw() {
* @return int
*/
public function get_id() {
- return $this->data['id'];
+ return $this->data['id'] ?? 0;
}
/**
@@ -158,6 +171,51 @@ public function get_ip() {
return $this->data['ip'];
}
+ /**
+ * Get withdraw charge
+ *
+ * @since DOKAN_SINCE
+ *
+ * @returns int|float
+ */
+ public function get_charge() {
+ return $this->data['charge'];
+ }
+
+ /**
+ * Get withdraw revivable amount after deducting the charge amount.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @returns int|float
+ */
+ public function get_receivable_amount() {
+ return $this->data['receivable'];
+ }
+
+ /**
+ * Get withdraw charge information.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @returns array
+ */
+ public function get_charge_data() {
+ $charge_data = $this->data['charge_data'];
+ if ( ! empty( $this->get_method() ) && empty( $this->data['charge_data'] ) ) {
+ $default_val = [
+ 'fixed' => 0.00,
+ 'percentage' => 0.00,
+ ];
+ $all_charges = dokan_withdraw_get_method_charges();
+
+ $charge_data = array_key_exists( $this->get_method(), $all_charges ) ? $all_charges[ $this->get_method() ] : $default_val;
+ $this->set_charge_data( $charge_data );
+ }
+
+ return $charge_data;
+ }
+
/**
* Set user_id
*
@@ -270,6 +328,89 @@ public function set_ip( $ip ) {
return $this;
}
+ /**
+ * Sets charge.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @param $amount
+ *
+ * @return \WeDevs\Dokan\Withdraw\Withdraw
+ */
+ public function set_charge( $amount ) {
+ $this->data['charge'] = floatval( $amount );
+
+ return $this;
+ }
+
+ /**
+ * Set receivable amount
+ *
+ * @since DOKAN_SINCE
+ *
+ * @param $receivable
+ *
+ * @return \WeDevs\Dokan\Withdraw\Withdraw
+ */
+ public function set_recivable( $receivable ) {
+ $this->data['receivable'] = floatval( $receivable );
+
+ return $this;
+ }
+
+ /**
+ * Sets charge data.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @param $charge_data array
+ *
+ * @return \WeDevs\Dokan\Withdraw\Withdraw
+ */
+ public function set_charge_data( $charge_data ) {
+ $this->data['charge_data'] = $charge_data;
+
+ return $this;
+ }
+
+ /**
+ * Calculate withdraw charge
+ *
+ * @since DOKAN_SINCE
+ *
+ * @return \WeDevs\Dokan\Withdraw\Withdraw
+ */
+ public function calculate_charge() {
+ $charge_data = $this->get_charge_data();
+ $fixed = $charge_data['fixed'];
+ $percentage = $charge_data['percentage'];
+ $charge = 0;
+
+ if ( ! empty( $fixed ) ) {
+ $charge += (float) $fixed;
+ }
+
+ if ( ! empty( $percentage ) ) {
+ $charge += $percentage / 100 * (float) $this->get_amount();
+ }
+
+ $this->set_charge( $charge );
+ $this->set_recivable( floatval( $this->get_amount() - floatval( $charge ) ) );
+
+ return $this;
+ }
+
+ /**
+ * Returns withdraw data.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @return array
+ */
+ public function get_data(): array {
+ return $this->data;
+ }
+
/**
* Create or update a withdraw
*
@@ -295,13 +436,30 @@ public function save() {
protected function create() {
global $wpdb;
- $this->data['details'] = maybe_serialize( dokan()->withdraw->get_formatted_details( $this->data['method'], absint( $this->data['user_id'] ) ) );
+ $this->calculate_charge();
+
+ $details = dokan()->withdraw->get_formatted_details( $this->data['method'], absint( $this->data['user_id'] ) );
+
+ $details['charge'] = $this->get_charge();
+ $details['receivable'] = $this->get_receivable_amount();
+ $details['charge_data'] = $this->get_charge_data();
+
+ $this->data['details'] = maybe_serialize( apply_filters( 'dokan_withdraw_request_details_data', $details, $this ) );
unset( $this->data['id'] );
$inserted = $wpdb->insert(
$wpdb->dokan_withdraw,
- $this->data,
+ [
+ 'user_id' => $this->get_user_id(),
+ 'amount' => $this->get_amount(),
+ 'date' => $this->get_date(),
+ 'status' => $this->get_status(),
+ 'method' => $this->get_method(),
+ 'note' => $this->get_note(),
+ 'details' => $this->get_details(),
+ 'ip' => $this->get_ip(),
+ ],
[ '%d', '%s', '%s', '%d', '%s', '%s', '%s', '%s' ]
);
diff --git a/includes/Withdraw/functions.php b/includes/Withdraw/functions.php
index 9696351a61..760f009b21 100644
--- a/includes/Withdraw/functions.php
+++ b/includes/Withdraw/functions.php
@@ -12,12 +12,14 @@
function dokan_withdraw_register_methods() {
$methods = [
'paypal' => [
- 'title' => __( 'PayPal', 'dokan-lite' ),
- 'callback' => 'dokan_withdraw_method_paypal',
+ 'title' => __( 'PayPal', 'dokan-lite' ),
+ 'callback' => 'dokan_withdraw_method_paypal',
+ 'apply_charge' => true,
],
'bank' => [
- 'title' => __( 'Bank Transfer', 'dokan-lite' ),
- 'callback' => 'dokan_withdraw_method_bank',
+ 'title' => __( 'Bank Transfer', 'dokan-lite' ),
+ 'callback' => 'dokan_withdraw_method_bank',
+ 'apply_charge' => true,
],
];
@@ -113,7 +115,7 @@ function dokan_withdraw_get_method_title( $method_key, $request = null ) {
/**
* @since 3.3.7 added filter dokan_get_withdraw_method_title
*/
- return apply_filters( 'dokan_get_withdraw_method_title', isset( $registered[ $method_key ] ) ? $registered[ $method_key ]['title'] : ucfirst( $method_key ), $method_key, $request );
+ return apply_filters( 'dokan_get_withdraw_method_title', isset( $registered[ $method_key ] ) ? $registered[ $method_key ]['title'] : ucfirst( $method_key ), $method_key, $request );
}
/**
@@ -228,7 +230,7 @@ function dokan_bank_payment_required_fields() {
// Filtering out all payment fields except dokan bank payment available fields.
$fields = array_filter(
$required_fields,
- function( $key ) use ( $available ) {
+ function ( $key ) use ( $available ) {
return in_array( $key, $available, true );
},
ARRAY_FILTER_USE_KEY
@@ -313,7 +315,7 @@ function dokan_bank_payment_fields_placeholders() {
],
'declaration' => [
'label' => __( 'I attest that I am the owner and have full authorization to this bank account', 'dokan-lite' ),
- 'placeholder' => __( '', 'dokan-lite' ),
+ 'placeholder' => __( '', 'dokan-lite' ), // phpcs:ignore
],
'form_caution' => [
'label' => __( 'Please double-check your account information!', 'dokan-lite' ),
@@ -512,3 +514,49 @@ function dokan_is_withdraw_method_enabled( $method_id ) {
&& array_key_exists( $method_id, $payment_methods )
&& ! empty( $payment_methods[ $method_id ] );
}
+
+/**
+ * Get registered withdraw methods suitable for Settings Api
+ *
+ * @return array
+ */
+function dokan_withdraw_get_chargeable_methods() {
+ $methods = [];
+ $registered = dokan_withdraw_register_methods();
+
+ foreach ( $registered as $key => $value ) {
+ if ( ! empty( $value['apply_charge'] ) ) {
+ $methods[ $key ] = $value['title'];
+ }
+ }
+
+ return $methods;
+}
+
+/**
+ * Returns all withdraw methods charges saved.
+ *
+ * @since DOKAN_SINCE
+ *
+ * @return array
+ */
+function dokan_withdraw_get_method_charges() {
+ $charges = dokan_get_option( 'withdraw_charges', 'dokan_withdraw', [] );
+ $all_methods = array_keys( dokan_withdraw_get_methods() );
+ $chargeable_methods = array_keys( dokan_withdraw_get_chargeable_methods() );
+ $default_val = [
+ 'fixed' => 0.00,
+ 'percentage' => 0.00,
+ ];
+
+ foreach ( $all_methods as $method ) {
+ if ( empty( $charges ) || ! is_array( $charges ) || ! in_array( $method, $chargeable_methods, true ) ) {
+ $charges[ $method ] = $default_val;
+ } else {
+ $charges[ $method ]['fixed'] = ! empty( $charges[ $method ]['fixed'] ) ? (float) wc_format_decimal( $charges[ $method ]['fixed'] ) : 0.00;
+ $charges[ $method ]['percentage'] = ! empty( $charges[ $method ]['percentage'] ) ? (float) wc_format_decimal( $charges[ $method ]['percentage'] ) : 0.00;
+ }
+ }
+
+ return $charges;
+}
diff --git a/src/admin/components/CombineInput.vue b/src/admin/components/CombineInput.vue
new file mode 100644
index 0000000000..9ad2173f24
--- /dev/null
+++ b/src/admin/components/CombineInput.vue
@@ -0,0 +1,113 @@
+
+