From ac8cfe42ed6d13a34572571728281591ebbf706f Mon Sep 17 00:00:00 2001 From: Aunshon Date: Thu, 14 Nov 2024 16:58:52 +0600 Subject: [PATCH] Enhancement/commission restructure (#2027) * Added tailwindcss * Added tailwindcss * Fix broken design after adding tailwindcss * Enable autoprefixer * Fix broken style of admin notice * Fix whats new icon style * Redesign combine commission * Build fixed commission component * Fix broken design * Responsive dokan menu and earning by commission * Earning by commission done * Category commission on going * Added commission meta-box. * Added commission meta-box. * Added commission meta-box. * Related and suborder done * Separate commission and sun/related order html codes into templates. * Separate commission and sun/related order html codes into templates. * Fix tailwind broken design * Fix tailwind broken design * Fix tailwind broken design * Update tailwind.config.js Disabling preflight. ```js corePlugins: { preflight: false, }, ``` * Update: tailwind css configuration. * Category commission save done * Add vendor single page * Add vendor payment images * Remove commission from user profile php end * Moved product commission to lite Moved category commission components to lite Removed category commission in woocommerce category page add & edit * Adding category commission in the setup wizard * Fix: style of commission in admin setup wizard * Category commission added on setup wizard done * Add new commission calculation classes * Added order item refund support in order item commission, rewrite the commission system. * Add flat, percentage and combine support to new commission system * Fix commission calculation. * Start the new commission system in Commission.php * Integrated the new commission system to Commission.php * Integrated the new commission system to Commission.php and showed earning on vendor product list. * Show commission on product edit page * Convert the commission class into structured class * Fix: commission details text * Fix: related orders list after refund. * Test case for a category commission is done. writing fixed commission. * Add tesing for dokan commission * Fix: global strategy commission * add strategy tests * Add get_earning_by_product method test case * Dokan commission unit test added. * Adding upgrade for a commission * Commission upgrader added. * Upgrader added for commission. Added test case for combine commission with empty price. * Fix: variation product commission data. the variation product commission will be same as parent product. * Fix style of CategoryBasedCommission.vue component * Add commenting for combine commission. * Add commenting for CommissionSettings.php * Fix save product commission data. * remove useless files * Make the calculate_gateway_fee method same as in the commission.php * Fix order metadata check * Restructure the commission files. * Restructure the commission files. * Restructure the commission files. * Update variable and function naming * Refactor codes * Code refactor. * Add commission api * Fix commission api permission check * Fix type of category helper * Codes refactor * Refactor codes * Fix phpstan error to level-5 * Refactor codes * Fix styles * Fix failed tests * Fix qa issues * Fix category commission component styles Fix Fixed commission component styles Show shipping tax and shipping tax recipient amount in order details page on commission section. Fix style commission ui in vendor commission setting * add commission delete functionality in vendor * Fix the type of commission amount * Add Commission tests * Add additional commission tests and Refactor some methods * Fix a test and refactor api utility mtehods * Fix invalid page number issue * Add time for slow tests and fix enpoint issue * Fix qu issues * Fix qa issues * Fix commission test files directory. * Add commission tests * Update commission tests prequisite and sitesetup,plugin setup methods * Skip plugin setup on CI * Fix a test * Add multivendor commission test * update tests & methods * Fix combine input debounce timer * Resolve test file conflicts * Update tests data & interfaces * Fix category commission behavior. * Fix: lint issues * Fix category based commission style. Fix price decimal consistency * Tooltip added for commission * Added tooltip in product edit page. * Add fees class into ServiceProvider.php class. * Update test data * Fix test data issue * Fix failed tests * Update api env setup * Fix minor test suite issues --------- Co-authored-by: Shazahanul Islam Shohag Co-authored-by: shashwata --- assets/images/payments/bank.svg | 5 + assets/images/payments/d-paypal.svg | 16 + assets/images/payments/d-stripe.svg | 15 + assets/images/payments/mangopay.svg | 16 + assets/images/payments/payment-bag.svg | 4 + assets/images/payments/paypal.svg | 15 + assets/images/payments/razorpay.svg | 12 + assets/images/payments/skrill.svg | 4 + assets/images/payments/stripe.svg | 11 + assets/src/js/product-category-ui.js | 2 + assets/src/js/product-editor.js | 63 + .../commission/AdminCommission.vue | 89 + .../src/js/setup-wizard/commission/index.js | 17 + .../src/js/setup-wizard/commission/style.css | 4 + .../commission/tailwind-commission.config.js | 19 + deprecated/class-dokan-taxonomy-walker.php | 5 - includes/Admin/Settings.php | 77 +- includes/Admin/SetupWizard.php | 98 +- includes/Admin/UserProfile.php | 23 - includes/Assets.php | 31 +- includes/Commission.php | 755 ++------ includes/Commission/Calculator.php | 80 + .../Commission/Formula/AbstractFormula.php | 189 ++ includes/Commission/Formula/CategoryBased.php | 354 ++++ includes/Commission/Formula/Combine.php | 198 ++ includes/Commission/Formula/Fixed.php | 226 +++ includes/Commission/Formula/Flat.php | 184 ++ includes/Commission/Formula/Percentage.php | 159 ++ includes/Commission/FormulaFactory.php | 48 + includes/Commission/Model/Commission.php | 308 +++ includes/Commission/Model/Setting.php | 217 +++ includes/Commission/Settings/Builder.php | 41 + .../Commission/Settings/DefaultSetting.php | 43 + .../Commission/Settings/GlobalSetting.php | 78 + .../Commission/Settings/InterfaceSetting.php | 33 + includes/Commission/Settings/OrderItem.php | 135 ++ includes/Commission/Settings/Product.php | 89 + includes/Commission/Settings/Vendor.php | 97 + .../Strategies/AbstractStrategy.php | 41 + .../Commission/Strategies/DefaultStrategy.php | 50 + .../Commission/Strategies/GlobalStrategy.php | 71 + includes/Commission/Strategies/OrderItem.php | 125 ++ includes/Commission/Strategies/Product.php | 60 + includes/Commission/Strategies/Vendor.php | 86 + .../Providers/ServiceProvider.php | 1 + includes/Fees.php | 268 +++ includes/Order/Admin/Hooks.php | 150 +- includes/Product/Hooks.php | 97 + includes/Product/Manager.php | 55 +- includes/ProductCategory/Helper.php | 6 +- includes/REST/AdminMiscController.php | 40 + includes/REST/CommissionControllerV1.php | 143 ++ includes/REST/Manager.php | 35 +- includes/REST/ProductControllerV2.php | 2 + includes/REST/StoreController.php | 28 +- includes/Upgrade/Upgrades.php | 1 + .../V_4_0_0_UpdateCommissions.php | 130 ++ includes/Upgrade/Upgrades/V_4_0_0.php | 140 ++ includes/Vendor/Manager.php | 8 + includes/Vendor/Vendor.php | 50 +- includes/Walkers/CategoryDropdownSingle.php | 56 - includes/Walkers/TaxonomyDropdown.php | 20 +- includes/functions.php | 185 +- includes/wc-template.php | 18 + lib/class.category-walker.php | 16 - lib/class.taxonomy-walker.php | 20 - src/admin/components/CombineInput.vue | 99 +- .../Commission/CategoryBasedCommission.vue | 365 ++++ src/admin/components/Commission/index.js | 1 + src/admin/components/Commission/style.css | 4 + .../tailwind-category-commission.config.js | 20 + src/admin/components/Currency.vue | 2 +- src/admin/components/Fields.vue | 143 +- .../components/Fields/WithdrawCharges.vue | 17 + .../components/VendorCommissionFields.vue | 130 ++ src/admin/pages/AddVendor.vue | 7 +- src/admin/pages/Settings.vue | 76 +- src/admin/pages/VendorPaymentFields.vue | 65 - src/admin/pages/VendorSingle.vue | 1692 +++++++++++++++++ src/admin/pages/Vendors.vue | 6 +- src/admin/router/index.js | 8 +- src/utils/Bootstrap.js | 4 + tailwind.config.js | 8 +- .../admin-setup-wizard/step-commission.php | 16 + templates/admin-setup-wizard/step-selling.php | 21 - templates/orders/commission-meta-box-html.php | 393 ++++ templates/orders/listing.php | 12 +- .../sub-order-related-order-meta-box-html.php | 111 ++ templates/products/edit-product-single.php | 41 +- templates/products/products-listing-row.php | 10 + templates/products/products-listing.php | 1 + templates/products/tmpl-add-product-popup.php | 1 - .../src/Commission/CommissionModelTest.php | 123 ++ tests/php/src/Commission/CommissionTest.php | 1133 +++++++++++ .../Commission/Formula/CategoryBasedTest.php | 268 +++ .../src/Commission/Formula/CombineTest.php | 199 ++ .../php/src/Commission/Formula/FixedTest.php | 182 ++ tests/php/src/Commission/Formula/FlatTest.php | 176 ++ .../src/Commission/Formula/PercentageTest.php | 176 ++ .../src/Commission/Strategy/GlobalTest.php | 518 +++++ .../src/Commission/Strategy/ProductTest.php | 304 +++ .../src/Commission/Strategy/VendorTest.php | 533 ++++++ tests/php/src/CommissionTest.php | 474 ----- tests/pw/.prettierrc | 2 +- tests/pw/feature-map/feature-map.yml | 17 + tests/pw/pages/adminPage.ts | 10 +- tests/pw/pages/basePage.ts | 11 +- tests/pw/pages/commissionPage.ts | 159 ++ tests/pw/pages/productsPage.ts | 22 +- tests/pw/pages/selectors.ts | 93 +- tests/pw/pages/settingsPage.ts | 9 +- tests/pw/pages/storesPage.ts | 224 +-- tests/pw/pages/vendorAuctionsPage.ts | 2 +- tests/pw/pages/vendorBookingPage.ts | 4 +- tests/pw/pages/vendorReturnRequestPage.ts | 2 +- tests/pw/tests/api/calculation.spec.ts | 759 +++++--- tests/pw/tests/api/commissions.spec.ts | 1 - tests/pw/tests/e2e/commission.spec.ts | 98 + tests/pw/tests/e2e/coupons.spec.ts | 1 - tests/pw/tests/e2e/euCompliance.spec.ts | 4 +- tests/pw/tests/e2e/stores.spec.ts | 2 +- tests/pw/tests/e2e/vendorSettings.spec.ts | 2 +- tests/pw/types/global.d.ts | 1 + tests/pw/utils/apiUtils.ts | 1 + tests/pw/utils/calculationHelpers.ts | 142 ++ tests/pw/utils/dbData.ts | 33 +- tests/pw/utils/dbUtils.ts | 42 +- tests/pw/utils/helpers.ts | 203 +- tests/pw/utils/interfaces.ts | 20 +- tests/pw/utils/payloads.ts | 139 +- tests/pw/utils/pwMatchers.ts | 32 + tests/pw/utils/schemas.ts | 2 +- tests/pw/utils/testData.ts | 78 +- webpack.config.js | 3 + 134 files changed, 12924 insertions(+), 2195 deletions(-) create mode 100644 assets/images/payments/bank.svg create mode 100644 assets/images/payments/d-paypal.svg create mode 100644 assets/images/payments/d-stripe.svg create mode 100644 assets/images/payments/mangopay.svg create mode 100644 assets/images/payments/payment-bag.svg create mode 100644 assets/images/payments/paypal.svg create mode 100644 assets/images/payments/razorpay.svg create mode 100644 assets/images/payments/skrill.svg create mode 100644 assets/images/payments/stripe.svg create mode 100644 assets/src/js/setup-wizard/commission/AdminCommission.vue create mode 100644 assets/src/js/setup-wizard/commission/index.js create mode 100644 assets/src/js/setup-wizard/commission/style.css create mode 100644 assets/src/js/setup-wizard/commission/tailwind-commission.config.js delete mode 100644 deprecated/class-dokan-taxonomy-walker.php create mode 100644 includes/Commission/Calculator.php create mode 100644 includes/Commission/Formula/AbstractFormula.php create mode 100644 includes/Commission/Formula/CategoryBased.php create mode 100644 includes/Commission/Formula/Combine.php create mode 100644 includes/Commission/Formula/Fixed.php create mode 100644 includes/Commission/Formula/Flat.php create mode 100644 includes/Commission/Formula/Percentage.php create mode 100644 includes/Commission/FormulaFactory.php create mode 100644 includes/Commission/Model/Commission.php create mode 100644 includes/Commission/Model/Setting.php create mode 100644 includes/Commission/Settings/Builder.php create mode 100644 includes/Commission/Settings/DefaultSetting.php create mode 100644 includes/Commission/Settings/GlobalSetting.php create mode 100644 includes/Commission/Settings/InterfaceSetting.php create mode 100644 includes/Commission/Settings/OrderItem.php create mode 100644 includes/Commission/Settings/Product.php create mode 100644 includes/Commission/Settings/Vendor.php create mode 100644 includes/Commission/Strategies/AbstractStrategy.php create mode 100644 includes/Commission/Strategies/DefaultStrategy.php create mode 100644 includes/Commission/Strategies/GlobalStrategy.php create mode 100644 includes/Commission/Strategies/OrderItem.php create mode 100644 includes/Commission/Strategies/Product.php create mode 100644 includes/Commission/Strategies/Vendor.php create mode 100644 includes/Fees.php create mode 100644 includes/REST/CommissionControllerV1.php create mode 100644 includes/Upgrade/Upgrades/BackgroundProcesses/V_4_0_0_UpdateCommissions.php create mode 100644 includes/Upgrade/Upgrades/V_4_0_0.php delete mode 100644 includes/Walkers/CategoryDropdownSingle.php delete mode 100644 lib/class.category-walker.php delete mode 100644 lib/class.taxonomy-walker.php create mode 100644 src/admin/components/Commission/CategoryBasedCommission.vue create mode 100644 src/admin/components/Commission/index.js create mode 100644 src/admin/components/Commission/style.css create mode 100644 src/admin/components/Commission/tailwind-category-commission.config.js create mode 100644 src/admin/components/VendorCommissionFields.vue create mode 100644 src/admin/pages/VendorSingle.vue create mode 100644 templates/admin-setup-wizard/step-commission.php create mode 100644 templates/orders/commission-meta-box-html.php create mode 100644 templates/orders/sub-order-related-order-meta-box-html.php create mode 100644 tests/php/src/Commission/CommissionModelTest.php create mode 100644 tests/php/src/Commission/CommissionTest.php create mode 100644 tests/php/src/Commission/Formula/CategoryBasedTest.php create mode 100644 tests/php/src/Commission/Formula/CombineTest.php create mode 100644 tests/php/src/Commission/Formula/FixedTest.php create mode 100644 tests/php/src/Commission/Formula/FlatTest.php create mode 100644 tests/php/src/Commission/Formula/PercentageTest.php create mode 100644 tests/php/src/Commission/Strategy/GlobalTest.php create mode 100644 tests/php/src/Commission/Strategy/ProductTest.php create mode 100644 tests/php/src/Commission/Strategy/VendorTest.php delete mode 100644 tests/php/src/CommissionTest.php create mode 100644 tests/pw/pages/commissionPage.ts create mode 100644 tests/pw/tests/e2e/commission.spec.ts create mode 100644 tests/pw/utils/calculationHelpers.ts diff --git a/assets/images/payments/bank.svg b/assets/images/payments/bank.svg new file mode 100644 index 0000000000..18611d1a01 --- /dev/null +++ b/assets/images/payments/bank.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/payments/d-paypal.svg b/assets/images/payments/d-paypal.svg new file mode 100644 index 0000000000..0f1d548a1f --- /dev/null +++ b/assets/images/payments/d-paypal.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/payments/d-stripe.svg b/assets/images/payments/d-stripe.svg new file mode 100644 index 0000000000..bb7f2a220c --- /dev/null +++ b/assets/images/payments/d-stripe.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/payments/mangopay.svg b/assets/images/payments/mangopay.svg new file mode 100644 index 0000000000..c3ca95fcb6 --- /dev/null +++ b/assets/images/payments/mangopay.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/images/payments/payment-bag.svg b/assets/images/payments/payment-bag.svg new file mode 100644 index 0000000000..5a5782a657 --- /dev/null +++ b/assets/images/payments/payment-bag.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/payments/paypal.svg b/assets/images/payments/paypal.svg new file mode 100644 index 0000000000..1a75439683 --- /dev/null +++ b/assets/images/payments/paypal.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/images/payments/razorpay.svg b/assets/images/payments/razorpay.svg new file mode 100644 index 0000000000..999a037e38 --- /dev/null +++ b/assets/images/payments/razorpay.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/payments/skrill.svg b/assets/images/payments/skrill.svg new file mode 100644 index 0000000000..fa10472858 --- /dev/null +++ b/assets/images/payments/skrill.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/images/payments/stripe.svg b/assets/images/payments/stripe.svg new file mode 100644 index 0000000000..8ebc3b802e --- /dev/null +++ b/assets/images/payments/stripe.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/src/js/product-category-ui.js b/assets/src/js/product-category-ui.js index e61799b62c..8928a0dd54 100644 --- a/assets/src/js/product-category-ui.js +++ b/assets/src/js/product-category-ui.js @@ -51,6 +51,8 @@ removeCatBox() { $( this ).closest( '.dokan-select-product-category-container' )[0].remove(); + // Do any action when click remove category. + wp.hooks.doAction( 'dokan_removed_multistep_category' ); }, categoryLiClick() { diff --git a/assets/src/js/product-editor.js b/assets/src/js/product-editor.js index c8c0e3c630..9c2a5886f9 100755 --- a/assets/src/js/product-editor.js +++ b/assets/src/js/product-editor.js @@ -73,6 +73,20 @@ this.setCorrectProductId(); $( 'body' ).trigger( 'dokan-product-editor-loaded', this ); + + $( "input.dokan-product-regular-price, input.dokan-product-sales-price" ).on( 'keyup', _.debounce( () => { + Dokan_Editor.dokan_show_earning_suggestion( Dokan_Editor.earning_suggestion_callbak ); + }, 750 ) ); + + if ( wp && wp.hooks && wp.hooks.addAction ) { + wp.hooks.addAction( 'dokan_selected_multistep_category', 'dokan-get-product-earning-suggestion', function() { + Dokan_Editor.dokan_show_earning_suggestion( Dokan_Editor.earning_suggestion_callbak ); + } ); + + wp.hooks.addAction( 'dokan_removed_multistep_category', 'dokan-get-product-earning-suggestion', function() { + Dokan_Editor.dokan_show_earning_suggestion( Dokan_Editor.earning_suggestion_callbak ); + } ); + } }, setCorrectProductId : function () { @@ -923,6 +937,55 @@ }); downloadable_frame.open(); + }, + + dokan_show_earning_suggestion: function( callback ) { + let commission = $('span.vendor-earning').attr( 'data-commission' ); + let product_id = $( 'span.vendor-earning' ).attr( 'data-product-id' ); + let product_price = $( 'input.dokan-product-regular-price' ).val(); + let sale_price = $( 'input.dokan-product-sales-price' ).val(); + let earning_suggestion = $('.simple-product span.vendor-price'); + let category_ids = $('input[name="chosen_product_cat[]"]').map(function() { + return $(this).val(); + }).get(); + + jQuery.ajax({ + url: window.dokan.rest.root + `dokan/v1/commission`, + beforeSend: function ( xhr ) { + xhr.setRequestHeader( 'X-WP-Nonce', window.dokan.rest.nonce ); + }, + type: 'GET', + data: { + product_id: product_id, + amount: sale_price ? sale_price : product_price, + // vendor_id + category_ids, + context: 'seller' + } + }).done( ( response ) => { + if ( ! isNaN( response ) ) { + earning_suggestion.html( response ); + } + + if ( typeof callback === 'function' ) { + callback(); + } + } ); + }, + + earning_suggestion_callbak: function() { + + if ( $( '#product_type' ).val() == 'simple' || $( '#product_type' ).text() == '' ) { + if ( Number( $('.simple-product span.vendor-price').text() ) < 0 ) { + $( $('.dokan-product-less-price-alert').removeClass('dokan-hide') ); + $( 'input[type=submit]' ).attr( 'disabled', 'disabled' ); + $( 'button[type=submit]' ).attr( 'disabled', 'disabled' ); + } else { + $( $('.dokan-product-less-price-alert').addClass('dokan-hide') ); + $( 'input[type=submit]' ).removeAttr( 'disabled'); + $( 'button[type=submit]' ).removeAttr( 'disabled'); + } + } } }; diff --git a/assets/src/js/setup-wizard/commission/AdminCommission.vue b/assets/src/js/setup-wizard/commission/AdminCommission.vue new file mode 100644 index 0000000000..26a2558fbd --- /dev/null +++ b/assets/src/js/setup-wizard/commission/AdminCommission.vue @@ -0,0 +1,89 @@ + + + + + + diff --git a/assets/src/js/setup-wizard/commission/index.js b/assets/src/js/setup-wizard/commission/index.js new file mode 100644 index 0000000000..0614f64634 --- /dev/null +++ b/assets/src/js/setup-wizard/commission/index.js @@ -0,0 +1,17 @@ +import AdminCommission from './AdminCommission.vue' + +const Vue = dokan_get_lib('Vue'); +import './style.css'; + +document.addEventListener("DOMContentLoaded", function() { + let element = document.getElementById( 'dokan-setup-wizard-commission-wrapper' ); + + if ( ! element ) { + return; + } + + new Vue({ + el: '#dokan-setup-wizard-commission-wrapper', + render: h => h(AdminCommission), + }); +}); diff --git a/assets/src/js/setup-wizard/commission/style.css b/assets/src/js/setup-wizard/commission/style.css new file mode 100644 index 0000000000..fad1411ac7 --- /dev/null +++ b/assets/src/js/setup-wizard/commission/style.css @@ -0,0 +1,4 @@ +@config './tailwind-commission.config.js'; +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/assets/src/js/setup-wizard/commission/tailwind-commission.config.js b/assets/src/js/setup-wizard/commission/tailwind-commission.config.js new file mode 100644 index 0000000000..e693c2461e --- /dev/null +++ b/assets/src/js/setup-wizard/commission/tailwind-commission.config.js @@ -0,0 +1,19 @@ +/** @type {import('tailwindcss').Config} */ +const defaultTheme = require("tailwindcss/defaultTheme"); +module.exports = { + corePlugins: { + preflight: false, + }, + content: [ + './assets/src/js/setup-wizard/commission/**/*.{php,js,jsx,vue,ts,tsx}', + ], + theme: { + extend: { + screens: { + ...defaultTheme.screens, + 'd-xs': '360px', + } + } + }, + plugins: [], +}; diff --git a/deprecated/class-dokan-taxonomy-walker.php b/deprecated/class-dokan-taxonomy-walker.php deleted file mode 100644 index 450fe33959..0000000000 --- a/deprecated/class-dokan-taxonomy-walker.php +++ /dev/null @@ -1,5 +0,0 @@ - __( 'Select a commission type for vendor', 'dokan-lite' ), 'type' => 'select', 'options' => $commission_types, - 'default' => 'percentage', + 'default' => 'fixed', 'tooltip' => __( 'Select a commission type', 'dokan-lite' ), ], - 'admin_percentage' => [ - 'name' => 'admin_percentage', - 'label' => __( 'Admin Commission', 'dokan-lite' ), - 'desc' => __( 'Amount you get from each sale', 'dokan-lite' ), - 'default' => '10', - 'type' => 'price', - 'sanitize_callback' => 'wc_format_decimal', + 'commission_fixed_values' => [ + 'name' => 'commission_fixed_values', + 'label' => __( 'Admin Commission', 'dokan-lite' ), + 'type' => 'commission_fixed', + 'fields' => [ + 'percent_fee' => [ + 'name' => 'admin_percentage', + 'label' => __( 'Percent Fee', 'dokan-lite' ), + 'default' => '10', + 'type' => 'text', + 'desc' => __( 'Amount you will get from sales in percentage (10%)', 'dokan-lite' ), + 'required' => 'yes', + 'sanitize_callback' => 'wc_format_decimal', + 'response_sanitize_callback' => 'wc_format_decimal', + ], + 'fixed_fee' => [ + 'name' => 'additional_fee', + 'label' => __( 'Fixed Fee', 'dokan-lite' ), + 'default' => '10', + 'type' => 'text', + 'desc' => __( 'Amount you will get from sales in flat rate(+5)', 'dokan-lite' ), + 'required' => 'yes', + 'sanitize_callback' => 'wc_format_decimal', + 'response_sanitize_callback' => 'wc_format_localized_price', + ], + ], + 'default' => 'fixed', + 'min' => '0', + 'step' => 'any', + 'desc' => __( 'Amount you will get from sales in both percentage and fixed fee', 'dokan-lite' ), + 'sanitize_callback' => 'wc_format_decimal', + 'response_sanitize_callback' => 'wc_format_localized_price', + 'show_if' => [ + 'commission_type' => [ + 'equal' => 'fixed', + ], + ], + ], + 'commission_category_based_values' => [ + 'name' => 'commission_category_based_values', + 'type' => 'category_based_commission', + 'dokan_pro_commission' => 'yes', + 'label' => __( 'Admin Commission', 'dokan-lite' ), + 'desc' => __( 'Amount you will get from each sale', 'dokan-lite' ), + 'show_if' => [ + 'commission_type' => [ + 'equal' => 'category_based', + ], + ], + ], + ] + ); + + $selling_option_fees = apply_filters( + 'dokan_settings_selling_option_fees', [ + 'fee-recipients' => [ + 'name' => 'fee-recipients', + 'label' => __( 'Fee Recipients', 'dokan-lite' ), + 'type' => 'sub_section', + 'description' => __( 'Define the fees that admin or vendor will recive', 'dokan-lite' ), + 'content_class' => 'sub-section-styles', ], 'shipping_fee_recipient' => [ 'name' => 'shipping_fee_recipient', - 'label' => __( 'Shipping Fee Recipient', 'dokan-lite' ), + 'label' => __( 'Shipping Fee', 'dokan-lite' ), 'desc' => __( 'Who will be receiving the shipping fees? Note that, tax fees for corresponding shipping method will not be included with shipping fees.', 'dokan-lite' ), 'type' => 'radio', 'options' => [ @@ -517,7 +571,7 @@ public function get_settings_fields() { ], 'tax_fee_recipient' => [ 'name' => 'tax_fee_recipient', - 'label' => __( 'Product Tax Fee Recipient', 'dokan-lite' ), + 'label' => __( 'Product Tax Fee', 'dokan-lite' ), 'desc' => __( 'Who will be receiving the tax fees for products? Note that, shipping tax fees will not be included with product tax.', 'dokan-lite' ), 'type' => 'radio', 'options' => [ @@ -528,7 +582,7 @@ public function get_settings_fields() { ], 'shipping_tax_fee_recipient' => [ 'name' => 'shipping_tax_fee_recipient', - 'label' => __( 'Shipping Tax Fee Recipient', 'dokan-lite' ), + 'label' => __( 'Shipping Tax Fee', 'dokan-lite' ), 'desc' => __( 'Who will be receiving the tax fees for shipping?', 'dokan-lite' ), 'type' => 'radio', 'options' => [ @@ -604,6 +658,7 @@ public function get_settings_fields() { 'dokan_settings_selling_options', array_merge( $selling_option_commission, + $selling_option_fees, $selling_option_vendor_capability ) ), diff --git a/includes/Admin/SetupWizard.php b/includes/Admin/SetupWizard.php index 835ab9b2df..0525cc8d85 100644 --- a/includes/Admin/SetupWizard.php +++ b/includes/Admin/SetupWizard.php @@ -2,6 +2,8 @@ namespace WeDevs\Dokan\Admin; +use stdClass; + /** * Setup wizard class * @@ -91,6 +93,40 @@ public function enqueue_scripts() { wp_enqueue_style( 'wc-setup', WC()->plugin_url() . '/assets/css/wc-setup.css', [ 'dashicons', 'install' ], WC_VERSION ); wp_enqueue_style( 'dokan-setup', DOKAN_PLUGIN_ASSEST . '/css/setup.css', [ 'wc-setup' ], DOKAN_PLUGIN_VERSION ); + wp_enqueue_script( + 'dokan-vue-bootstrap', + DOKAN_PLUGIN_ASSEST . '/js/vue-bootstrap.js', + [ 'dokan-vue-vendor', 'dokan-i18n-jed', 'wp-hooks' ], + DOKAN_PLUGIN_VERSION, + [ 'in_footer' => true ] + ); + + wp_localize_script( + 'dokan-vue-bootstrap', + 'dokan', + dokan()->scripts->get_admin_localized_scripts() + ); + wp_enqueue_script( + 'dokan-setup-wizard-commission', + DOKAN_PLUGIN_ASSEST . '/js/dokan-setup-wizard-commission.js', + array( 'jquery', 'dokan-vue-bootstrap', 'dokan-accounting' ), + DOKAN_PLUGIN_VERSION, + [ 'in_footer' => true ] + ); + wp_enqueue_style( + 'dokan-setup-wizard-commission', + DOKAN_PLUGIN_ASSEST . '/css/dokan-setup-wizard-commission.css', + [ 'dokan-setup' ], + DOKAN_PLUGIN_VERSION + ); + + wp_enqueue_style( + 'dokan-category-commission', + DOKAN_PLUGIN_ASSEST . '/css/dokan-category-commission.css', + [], + DOKAN_PLUGIN_VERSION + ); + if ( 'off' === dokan_get_option( 'disable_dokan_fontawesome', 'dokan_appearance', 'off' ) ) { wp_enqueue_style( 'dokan-fontawesome' ); } @@ -155,11 +191,16 @@ protected function set_steps() { 'view' => [ $this, 'dokan_setup_store' ], 'handler' => [ $this, 'dokan_setup_store_save' ], ], - 'selling' => [ + 'selling' => [ 'name' => __( 'Selling', 'dokan-lite' ), 'view' => [ $this, 'dokan_setup_selling' ], 'handler' => [ $this, 'dokan_setup_selling_save' ], ], + 'commission' => [ + 'name' => __( 'Commission', 'dokan-lite' ), + 'view' => [ $this, 'dokan_setup_commission' ], + 'handler' => [ $this, 'dokan_setup_commission_save' ], + ], 'withdraw' => [ 'name' => __( 'Withdraw', 'dokan-lite' ), 'view' => [ $this, 'dokan_setup_withdraw' ], @@ -456,6 +497,35 @@ public function dokan_setup_selling() { dokan_get_template( 'admin-setup-wizard/step-selling.php', $args ); } + /** + * Commission step. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function dokan_setup_commission() { + $options = get_option( 'dokan_selling', [ 'admin_percentage' => 10 ] ); + + $admin_percentage = isset( $options['admin_percentage'] ) ? $options['admin_percentage'] : 10; + $additional_fee = isset( $options['additional_fee'] ) ? $options['additional_fee'] : 0; + $commission_category_based_values = isset( $options['commission_category_based_values'] ) ? $options['commission_category_based_values'] : new stdClass(); + $commission_type = ! empty( $options['commission_type'] ) ? $options['commission_type'] : 'fixed'; + + $args = apply_filters( + 'dokan_admin_setup_wizard_step_setup_selling_template_args', [ + 'commission_type' => $commission_type, + 'admin_percentage' => $admin_percentage, + 'additional_fee' => $additional_fee, + 'commission_category_based_values' => $commission_category_based_values, + 'dokanCommission' => dokan_commission_types(), + 'setup_wizard' => $this, + ] + ); + + dokan_get_template( 'admin-setup-wizard/step-commission.php', $args ); + } + /** * Save selling options. */ @@ -464,8 +534,6 @@ public function dokan_setup_selling_save() { $options = get_option( 'dokan_selling', [] ); $options['new_seller_enable_selling'] = isset( $_POST['new_seller_enable_selling'] ) ? 'on' : 'off'; - $options['commission_type'] = isset( $_POST['commission_type'] ) ? sanitize_text_field( wp_unslash( $_POST['commission_type'] ) ) : ''; - $options['admin_percentage'] = isset( $_POST['admin_percentage'] ) ? wc_format_decimal( sanitize_text_field( wp_unslash( $_POST['admin_percentage'] ) ) ) : 0; $options['order_status_change'] = isset( $_POST['order_status_change'] ) ? 'on' : 'off'; update_option( 'dokan_selling', $options ); @@ -476,6 +544,30 @@ public function dokan_setup_selling_save() { exit; } + /** + * Save commission options. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function dokan_setup_commission_save() { + check_admin_referer( 'dokan-setup' ); + + $options = get_option( 'dokan_selling', [] ); + $options['commission_type'] = isset( $_POST['dokan_commission_type'] ) ? sanitize_text_field( wp_unslash( $_POST['dokan_commission_type'] ) ) : 'fixed'; + $options['admin_percentage'] = isset( $_POST['dokan_commission_percentage'] ) ? wc_format_decimal( sanitize_text_field( wp_unslash( $_POST['dokan_commission_percentage'] ) ) ) : 0; + $options['additional_fee'] = isset( $_POST['dokan_commission_flat'] ) ? sanitize_text_field( wp_unslash( $_POST['dokan_commission_flat'] ) ) : 0; + $options['commission_category_based_values'] = isset( $_POST['dokan_commission_category_based'] ) ? wc_clean( json_decode( sanitize_text_field( wp_unslash( $_POST['dokan_commission_category_based'] ) ), true ) ) : []; + + update_option( 'dokan_selling', $options ); + + do_action( 'dokan_admin_setup_wizard_save_step_setup_commission', $options, [] ); + + wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) ); + exit; + } + /** * Withdraw Step. */ diff --git a/includes/Admin/UserProfile.php b/includes/Admin/UserProfile.php index 00a86458f6..3fcfb64cdd 100755 --- a/includes/Admin/UserProfile.php +++ b/includes/Admin/UserProfile.php @@ -65,8 +65,6 @@ public function add_meta_fields( $user ) { $publishing = get_user_meta( $user->ID, 'dokan_publishing', true ); $store_settings = dokan_get_store_info( $user->ID ); $banner = ! empty( $store_settings['banner'] ) ? absint( $store_settings['banner'] ) : 0; - $admin_commission = get_user_meta( $user->ID, 'dokan_admin_percentage', true ); - $admin_commission_type = get_user_meta( $user->ID, 'dokan_admin_percentage_type', true ); $feature_seller = get_user_meta( $user->ID, 'dokan_feature_seller', true ); $social_fields = dokan_get_social_profile_fields(); @@ -80,7 +78,6 @@ public function add_meta_fields( $user ) { $address_state = isset( $store_settings['address']['state'] ) ? $store_settings['address']['state'] : ''; $banner_width = dokan_get_vendor_store_banner_width(); $banner_height = dokan_get_vendor_store_banner_height(); - $admin_commission = ( 'flat' === $admin_commission_type ) ? wc_format_localized_price( $admin_commission ) : wc_format_localized_decimal( $admin_commission ); $country_state = array( 'country' => array( @@ -323,26 +320,6 @@ public function add_meta_fields( $user ) { - - - - -

- - - - - - - -

- - - diff --git a/includes/Assets.php b/includes/Assets.php index 596f0a429a..fc9e7c96a2 100644 --- a/includes/Assets.php +++ b/includes/Assets.php @@ -59,7 +59,8 @@ public function enqueue_admin_scripts( $hook ) { // load vue app inside the parent menu only if ( 'toplevel_page_dokan' === $hook ) { - $localize_script = $this->get_admin_localized_scripts(); + $localize_script = $this->get_admin_localized_scripts(); + $vue_admin_localize_script = $this->get_vue_admin_localized_scripts(); // Load common styles and scripts wp_enqueue_script( 'dokan-tinymce' ); @@ -89,6 +90,7 @@ public function enqueue_admin_scripts( $hook ) { // fire the admin app wp_enqueue_script( 'dokan-vue-admin' ); + wp_localize_script( 'dokan-vue-vendor', 'dokanAdmin', $vue_admin_localize_script ); if ( version_compare( $wp_version, '5.3', '<' ) ) { wp_enqueue_style( 'dokan-wp-version-before-5-3' ); @@ -211,6 +213,11 @@ public function get_vue_admin_routes() { 'name' => 'Vendors', 'component' => 'Vendors', ], + [ + 'path' => '/vendors/:id', + 'name' => 'VendorSingle', + 'component' => 'VendorSingle', + ], [ 'path' => '/dummy-data', 'name' => 'DummyData', @@ -580,6 +587,9 @@ public function enqueue_front_scripts() { } } + $vendor = dokan()->vendor->get( dokan_get_current_user_id() ); + $commision_settings = $vendor->get_commission_settings(); + $default_script = [ 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'dokan_reviews' ), @@ -590,8 +600,8 @@ public function enqueue_front_scripts() { ], '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() ), + 'vendor_percentage' => $commision_settings->get_percentage(), + 'commission_type' => $commision_settings->get_type(), 'rounding_precision' => wc_get_rounding_precision(), 'mon_decimal_point' => wc_get_price_decimal_separator(), 'currency_format_num_decimals' => wc_get_price_decimals(), @@ -1203,4 +1213,19 @@ public function get_admin_localized_scripts() { ] ); } + + /** + * Admin vue localized scripts + * + * @since DOKAN_SINCE + * + * @return array + */ + private function get_vue_admin_localized_scripts() { + return apply_filters( + 'dokan_vue_admin_localize_script', [ + 'commission_types' => dokan_commission_types(), + ] + ); + } } diff --git a/includes/Commission.php b/includes/Commission.php index f0040530b4..7e21d1c041 100644 --- a/includes/Commission.php +++ b/includes/Commission.php @@ -4,9 +4,15 @@ use WC_Order; use WC_Product; +use WeDevs\Dokan\Commission\Calculator; +use WeDevs\Dokan\Commission\Settings\DefaultSetting; +use WeDevs\Dokan\Commission\Strategies\DefaultStrategy; +use WeDevs\Dokan\Commission\Strategies\GlobalStrategy; +use WeDevs\Dokan\Commission\Strategies\OrderItem; +use WeDevs\Dokan\Commission\Strategies\Product; +use WeDevs\Dokan\Commission\Strategies\Vendor; use WeDevs\Dokan\ProductCategory\Helper; use WP_Error; -use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; /** * Dokan Commission Class @@ -42,23 +48,11 @@ class Commission { */ public $quantity = 0; - /** - * Class constructor - * - * @since 2.9.21 - * - * @return void - */ - public function __construct() { - add_filter( 'woocommerce_order_item_get_formatted_meta_data', [ $this, 'hide_extra_data' ] ); - add_action( 'woocommerce_order_status_changed', [ $this, 'calculate_gateway_fee' ], 100 ); - add_action( 'woocommerce_thankyou_ppec_paypal', [ $this, 'calculate_gateway_fee' ] ); - add_action( 'woocommerce_paypal_payments_order_captured', [ $this, 'calculate_gateway_fee' ], 99 ); - } - /** * Calculate gateway fee * + * @deprecated DOKAN_SINCE Use dokan()->fees->calculate_gateway_fee insted. + * * @since 2.9.21 * * @param int $order_id @@ -66,89 +60,15 @@ public function __construct() { * @return void */ public function calculate_gateway_fee( $order_id ) { - global $wpdb; - $order = wc_get_order( $order_id ); - $processing_fee = $this->get_processing_fee( $order ); - - if ( ! $processing_fee ) { - return; - } - - foreach ( $this->get_all_order_to_be_processed( $order ) as $tmp_order ) { - $gateway_fee_added = $tmp_order->get_meta( 'dokan_gateway_fee' ); - $vendor_earning = $this->get_earning_from_order_table( $tmp_order->get_id() ); - - if ( is_null( $vendor_earning ) || $gateway_fee_added ) { - continue; - } - - $gateway_fee = wc_format_decimal( ( $processing_fee / $order->get_total() ) * $tmp_order->get_total() ); - - // Ensure sub-orders also get the correct payment gateway fee (if any) - $gateway_fee = apply_filters( 'dokan_get_processing_gateway_fee', $gateway_fee, $tmp_order, $order ); - $net_amount = $vendor_earning - $gateway_fee; - $net_amount = apply_filters( 'dokan_orders_vendor_net_amount', $net_amount, $vendor_earning, $gateway_fee, $tmp_order, $order ); - - $wpdb->update( - $wpdb->dokan_orders, - [ 'net_amount' => (float) $net_amount ], - [ 'order_id' => $tmp_order->get_id() ], - [ '%f' ], - [ '%d' ] - ); - - $wpdb->update( - $wpdb->dokan_vendor_balance, - [ 'debit' => (float) $net_amount ], - [ - 'trn_id' => $tmp_order->get_id(), - 'trn_type' => 'dokan_orders', - ], - [ '%f' ], - [ '%d', '%s' ] - ); - - $tmp_order->update_meta_data( 'dokan_gateway_fee', $gateway_fee ); - $tmp_order->save(); - - if ( apply_filters( 'dokan_commission_log_gateway_fee_to_order_note', true, $tmp_order ) ) { - // translators: %s: Geteway fee - $tmp_order->add_order_note( sprintf( __( 'Payment gateway processing fee %s', 'dokan-lite' ), wc_format_decimal( $gateway_fee, 2 ) ) ); - } - //remove cache for seller earning - $cache_key = "get_earning_from_order_table_{$tmp_order->get_id()}_seller"; - Cache::delete( $cache_key ); - - // remove cache for seller earning - $cache_key = "get_earning_from_order_table_{$tmp_order->get_id()}_admin"; - Cache::delete( $cache_key ); - } - } - - /** - * Hide extra meta data - * - * @since 2.9.21 - * - * @param array - * - * @return array - */ - public function hide_extra_data( $formatted_meta ) { - $meta_to_hide = [ '_dokan_commission_rate', '_dokan_commission_type', '_dokan_additional_fee' ]; - - foreach ( $formatted_meta as $key => $meta ) { - if ( in_array( $meta->key, $meta_to_hide, true ) ) { - unset( $formatted_meta[ $key ] ); - } - } - - return $formatted_meta; + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->fees->calculate_gateway_fee()' ); + dokan()->fees->calculate_gateway_fee( $order_id ); } /** * Set order id * + * @deprecated DOKAN_SINCE + * * @since 2.9.21 * * @param int $id @@ -156,12 +76,15 @@ public function hide_extra_data( $formatted_meta ) { * @return void */ public function set_order_id( $id ) { + _deprecated_function( __METHOD__, 'DOKAN_SINCE' ); $this->order_id = $id; } /** * Set order line item id * + * @deprecated DOKAN_SINCE + * * @since 3.8.0 * * @param int $item_id @@ -169,34 +92,43 @@ public function set_order_id( $id ) { * @return void */ public function set_order_item_id( $item_id ) { + _deprecated_function( __METHOD__, 'DOKAN_SINCE' ); $this->order_item_id = absint( $item_id ); } /** * Get order id * + * @deprecated DOKAN_SINCE + * * @since 2.9.21 * * @return int */ public function get_order_id() { + _deprecated_function( __METHOD__, 'DOKAN_SINCE' ); return $this->order_id; } /** * Get order line item id * + * @deprecated DOKAN_SINCE + * * @since 3.8.0 * * @return int */ public function get_order_item_id() { + _deprecated_function( __METHOD__, 'DOKAN_SINCE' ); return $this->order_item_id; } /** * Set order quantity * + * @deprecated DOKAN_SINCE + * * @since 2.9.21 * * @param int $number @@ -204,17 +136,21 @@ public function get_order_item_id() { * @return void */ public function set_order_qunatity( $number ) { + _deprecated_function( __METHOD__, 'DOKAN_SINCE' ); $this->quantity = $number; } /** * Get order quantity * + * @deprecated DOKAN_SINCE + * * @since 2.9.21 * * @return int */ public function get_order_qunatity() { + _deprecated_function( __METHOD__, 'DOKAN_SINCE' ); return $this->quantity; } @@ -242,10 +178,17 @@ public function get_earning_by_product( $product, $context = 'seller', $price = $vendor_id = (int) dokan_get_vendor_by_product( $product, true ); $product_id = $product->get_id(); - $earning = $this->calculate_commission( $product_id, $product_price, $vendor_id ); - $earning = 'admin' === $context ? $product_price - $earning : $earning; + $commission = $this->get_commission( + [ + 'product_id' => $product_id, + 'total_amount' => $product_price, + 'total_quantity' => 1, + 'vendor_id' => $vendor_id, + ] + ); - return apply_filters( 'dokan_get_earning_by_product', $earning, $product, $context ); + $commission_or_earning = 'admin' === $context ? $commission->get_admin_commission() : $commission->get_vendor_earning(); + return apply_filters( 'dokan_get_earning_by_product', $commission_or_earning, $product, $context ); } /** @@ -255,7 +198,7 @@ public function get_earning_by_product( $product, $context = 'seller', $price = * @since 3.7.19 Shipping tax recipient support added. * * @param int|WC_Order $order Order. - * @param string $context + * @param string $context Accepted values are `admin`, `seller` * * @return float|void|WP_Error|null on failure */ @@ -282,197 +225,55 @@ public function get_earning_by_order( $order, $context = 'seller' ) { return apply_filters( 'dokan_order_admin_commission', $saved_fee, $order ); } - // Set user passed `order_id` - $this->set_order_id( $order->get_id() ); - // get earning from order table - $earning = $this->get_earning_from_order_table( $order->get_id(), $context ); - if ( ! is_null( $earning ) ) { - return $earning; + $earning_or_commission = $this->get_earning_from_order_table( $order->get_id(), $context ); + if ( ! is_null( $earning_or_commission ) ) { + return $earning_or_commission; } - $earning = 0; + $earning_or_commission = 0; $vendor_id = (int) $order->get_meta( '_dokan_vendor_id' ); foreach ( $order->get_items() as $item_id => $item ) { - // Set user passed `order_id` so that we can track if any commission_rate has been saved previously. - // Specially on order table `re-generation`. - $this->set_order_item_id( $item->get_id() ); - - // Set line item quantity so that we can use it later in the `\WeDevs\Dokan\Commission::prepare_for_calculation()` method - $this->set_order_qunatity( $item->get_quantity() ); - $product_id = $item->get_variation_id() ? $item->get_variation_id() : $item->get_product_id(); $refund = $order->get_total_refunded_for_item( $item_id ); if ( dokan_is_admin_coupon_applied( $order, $vendor_id, $product_id ) ) { - $earning += dokan_pro()->coupon->get_earning_by_admin_coupon( $order, $item, $context, $item->get_product(), $vendor_id, $refund ); + $earning_or_commission += dokan_pro()->coupon->get_earning_by_admin_coupon( $order, $item, $context, $item->get_product(), $vendor_id, $refund ); } else { $item_price = apply_filters( 'dokan_earning_by_order_item_price', $item->get_total(), $item, $order ); $item_price = $refund ? $item_price - $refund : $item_price; - $item_earning = $this->calculate_commission( $product_id, $item_price, $vendor_id ); - $item_earning = 'admin' === $context ? $item_price - $item_earning : $item_earning; - $earning += $item_earning; + $item_earning_or_commission = $this->get_commission( + [ + 'order_item_id' => $item->get_id(), + 'product_id' => $product_id, + 'total_amount' => $item_price, + 'total_quantity' => $item->get_quantity(), + 'vendor_id' => $vendor_id, + ], + true + ); + $item_earning_or_commission = 'admin' === $context ? $item_earning_or_commission->get_admin_commission() : $item_earning_or_commission->get_vendor_earning(); + $earning_or_commission += $item_earning_or_commission; } - - // reset order item id to zero - $this->set_order_item_id( 0 ); - // set order quantity to zero - $this->set_order_qunatity( 0 ); - } - - // reset order id to zero, we don't need this value anymore - $this->set_order_id( 0 ); - - if ( $context === $this->get_shipping_fee_recipient( $order ) ) { - $earning += wc_format_decimal( floatval( $order->get_shipping_total() ) ) - $order->get_total_shipping_refunded(); - } - - if ( $context === $this->get_tax_fee_recipient( $order->get_id() ) ) { - $earning += ( ( $order->get_total_tax() - $order->get_total_tax_refunded() ) - ( $order->get_shipping_tax() - $this->get_total_shipping_tax_refunded( $order ) ) ); } - if ( $context === $this->get_shipping_tax_fee_recipient( $order ) ) { - $earning += ( $order->get_shipping_tax() - $this->get_total_shipping_tax_refunded( $order ) ); + if ( $context === dokan()->fees->get_shipping_fee_recipient( $order ) ) { + $earning_or_commission += $order->get_shipping_total() - $order->get_total_shipping_refunded(); } - $earning = apply_filters_deprecated( 'dokan_order_admin_commission', [ $earning, $order, $context ], '2.9.21', 'dokan_get_earning_by_order' ); - - return apply_filters( 'dokan_get_earning_by_order', $earning, $order, $context ); - } - - /** - * Get global rate - * - * @since 2.9.21 - * - * @return float - */ - public function get_global_rate() { - return $this->validate_rate( dokan_get_option( 'admin_percentage', 'dokan_selling', 0 ) ); - } - - /** - * Get vendor wise commission rate - * - * @since 2.9.21 - * - * @param int $vendor_id - * - * @return float - */ - public function get_vendor_wise_rate( $vendor_id ) { - return $this->validate_rate( get_user_meta( $vendor_id, 'dokan_admin_percentage', true ) ); - } - - /** - * Get product wise commission rate - * - * @since 2.9.21 - * - * @param int $product_id - * - * @return float - */ - public function get_product_wise_rate( $product_id ) { - return $this->validate_rate( get_post_meta( $this->validate_product_id( $product_id ), '_per_product_admin_commission', true ) ); - } - - /** - * Validate product id (if it's a variable product, return it's parent id) - * - * @since 2.9.21 - * - * @param int $product_id - * - * @return int - */ - public function validate_product_id( $product_id ) { - $product = wc_get_product( $product_id ); - if ( ! $product ) { - return 0; + if ( $context === dokan()->fees->get_tax_fee_recipient( $order->get_id() ) ) { + $earning_or_commission += ( ( $order->get_total_tax() - $order->get_total_tax_refunded() ) - ( $order->get_shipping_tax() - dokan()->fees->get_total_shipping_tax_refunded( $order ) ) ); } - $parent_id = $product->get_parent_id(); - - return $parent_id ? $parent_id : $product_id; - } - - /** - * Get category wise commission rate - * - * @since 2.9.21 - * - * @param int $product_id - * - * @return float - */ - public function get_category_wise_rate( $product_id ) { - $terms = Helper::get_product_chosen_category( $this->validate_product_id( $product_id ) ); - - // Category commission will not applicable if 'Product Category Selection' is set as 'Multiple' in Dokan settings. - if ( ! is_array( $terms ) || empty( $terms ) || count( $terms ) > 1 || ! Helper::product_category_selection_is_single() ) { - return null; + if ( $context === dokan()->fees->get_shipping_tax_fee_recipient( $order ) ) { + $earning_or_commission += ( $order->get_shipping_tax() - dokan()->fees->get_total_shipping_tax_refunded( $order ) ); } - $term_id = $terms[0]; - $rate = ! $terms ? null : get_term_meta( $term_id, 'per_category_admin_commission', true ); + $earning_or_commission = apply_filters_deprecated( 'dokan_order_admin_commission', [ $earning_or_commission, $order, $context ], '2.9.21', 'dokan_get_earning_by_order' ); - return $this->validate_rate( $rate ); - } - - /** - * Get global commission type - * - * @since 2.9.21 - * - * @return string - */ - public function get_global_type() { - return dokan_get_option( 'commission_type', 'dokan_selling', 'percentage' ); - } - - /** - * Get vendor wise commission type - * - * @since 2.9.21 - * - * @param int $vendor_id - * - * @return string - */ - public function get_vendor_wise_type( $vendor_id ) { - return get_user_meta( $vendor_id, 'dokan_admin_percentage_type', true ); - } - - /** - * Get category wise commission type - * - * @since 2.9.21 - * - * @param int $product_id - * - * @return string - */ - public function get_category_wise_type( $product_id ) { - $terms = get_the_terms( $this->validate_product_id( $product_id ), 'product_cat' ); - $term_id = $terms[0]->term_id; - - return ! $terms ? null : get_term_meta( $term_id, 'per_category_admin_commission_type', true ); - } - - /** - * Get product wise commission type - * - * @since 2.9.21 - * - * @param int $product_id - * - * @return string - */ - public function get_product_wise_type( $product_id ) { - return get_post_meta( $this->validate_product_id( $product_id ), '_per_product_admin_commission_type', true ); + return apply_filters( 'dokan_get_earning_by_order', $earning_or_commission, $order, $context ); } /** @@ -493,196 +294,26 @@ public function validate_rate( $rate ) { } /** - * Get global earning - * - * @since 2.9.21 - * - * @param float $product_price - * - * @return float|null on failure - */ - public function get_global_earning( $product_price ) { - return $this->prepare_for_calculation( __FUNCTION__, null, $product_price ); - } - - /** - * Get vendor wise earning - * - * @since 2.9.21 - * - * @param int $vendor_id - * @param float $product_price - * - * @return float|null on failure - */ - public function get_vendor_wise_earning( $vendor_id, $product_price ) { - return $this->prepare_for_calculation( __FUNCTION__, $vendor_id, $product_price ); - } - - /** - * Get category wise earning - * - * @since 2.9.21 - * - * @param int $product_id - * @param float $product_price - * - * @return float|null on failure - */ - public function get_category_wise_earning( $product_id, $product_price ) { - if ( ! dokan()->is_pro_exists() ) { - return null; - } - - return $this->prepare_for_calculation( __FUNCTION__, $product_id, $product_price ); - } - - /** - * Get product wise earning - * - * @since 2.9.21 - * - * @param int $product_id - * @param int $product_price - * - * @return float|null on failure - */ - public function get_product_wise_earning( $product_id, $product_price ) { - if ( ! dokan()->is_pro_exists() ) { - return null; - } - - return $this->prepare_for_calculation( __FUNCTION__, $product_id, $product_price ); - } - - /** - * Prepare for calculation - * - * @since 2.9.21 - * - * @param callable $callable - * @param int $product_id - * @param float $product_price - * - * @return float | null on failure - */ - public function prepare_for_calculation( $callable, $product_id = 0, $product_price = 0 ) { - do_action( 'dokan_before_prepare_for_calculation', $callable, $product_id, $product_price, $this ); - - // If an order has been purchased previously, calculate the earning with the previously stated commission rate. - // It's important cause commission rate may get changed by admin during the order table `re-generation`. - $commission_rate = $this->get_order_item_id() ? wc_get_order_item_meta( $this->get_order_item_id(), '_dokan_commission_rate', true ) : null; - $commission_type = $this->get_order_item_id() ? wc_get_order_item_meta( $this->get_order_item_id(), '_dokan_commission_type', true ) : null; - $additional_fee = $this->get_order_item_id() ? wc_get_order_item_meta( $this->get_order_item_id(), '_dokan_additional_fee', true ) : null; - - if ( empty( $commission_rate ) ) { // this is the first time we are calculating commission for this order - // Set default value as null - $commission_rate = null; - $commission_type = null; - $additional_fee = null; - - $func_rate = str_replace( 'earning', 'rate', $callable ); - $func_type = str_replace( 'earning', 'type', $callable ); - $func_fee = str_replace( 'earning', 'additional_fee', $callable ); - - // get[product,category,vendor,global]_wise_rate - if ( is_callable( [ $this, $func_rate ] ) ) { - $commission_rate = $this->$func_rate( $product_id ); - } - - if ( is_null( $commission_rate ) ) { - return $commission_rate; - } - - // get[product,category,vendor,global]_wise_type - if ( is_callable( [ $this, $func_type ] ) ) { - $commission_type = $this->$func_type( $product_id ); - } - - // get[product,category,vendor,global]_wise_additional_fee - if ( is_callable( [ $this, $func_fee ] ) ) { - $additional_fee = $this->$func_fee( $product_id ); - } - - // Saving applied commission rates and types for current order item in order item meta. - wc_add_order_item_meta( $this->get_order_item_id(), '_dokan_commission_rate', $commission_rate ); - wc_add_order_item_meta( $this->get_order_item_id(), '_dokan_commission_type', $commission_type ); - wc_add_order_item_meta( $this->get_order_item_id(), '_dokan_additional_fee', $additional_fee ); - } - - /** - * If dokan pro doesn't exist but combine commission is found in database due to it was active before - * Then make the commission type 'flat'. We are making it flat cause when commission type is there in database - * But in option field, looks like flat commission is selected. - * - * @since 3.0.0 - */ - if ( ! dokan()->is_pro_exists() && 'combine' === $commission_type ) { - $commission_type = 'flat'; - } - - $earning = null; - - if ( 'flat' === $commission_type ) { - if ( (int) $this->get_order_qunatity() > 1 ) { - $commission_rate *= apply_filters( 'dokan_commission_multiply_by_order_quantity', $this->get_order_qunatity() ); - } - - // If `_dokan_item_total` returns value non-falsy value, it means the request is comming from the `order refund requst`. - // As it's `flat` fee, So modify `commission rate` to the correct amount to get refunded. (commission_rate/item_total)*product_price. - $item_total = 0; - if ( $this->get_order_id() ) { - $order = wc_get_order( $this->get_order_id() ); - $item_total = $order->get_meta( '_dokan_item_total', true ); - } - - if ( $item_total ) { - $commission_rate = ( $commission_rate / $item_total ) * $product_price; - } - - $earning = $product_price - $commission_rate; - } elseif ( 'percentage' === $commission_type ) { - $earning = ( $product_price * $commission_rate ) / 100; - $earning = $product_price - $earning; - - // vendor will get 100 percent if commission rate > 100 - if ( $commission_rate > 100 ) { - $earning = $product_price; - } - } - - return apply_filters( 'dokan_prepare_for_calculation', $earning, $commission_rate, $commission_type, $additional_fee, $product_price, $this->get_order_id() ); - } - - /** - * Get product wise additional fee + * Get vendor wise additional rate * - * @since 2.9.21 - * - * @param int $product_id - * - * @return float|null on failure - */ - public function get_product_wise_additional_fee( $product_id ) { - return $this->validate_rate( get_post_meta( $this->validate_product_id( $product_id ), '_per_product_admin_additional_fee', true ) ); - } - - /** - * Get global wise additional fee + * @deprecated DOKAN_SINCE Use dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_percentage() insted * * @since 2.9.21 * - * @param int $product_id + * @param int $vendor_id * * @return float|null on failure */ - public function get_global_additional_fee() { - return $this->validate_rate( dokan_get_option( 'additional_fee', 'dokan_selling', 0 ) ); + public function get_vendor_wise_rate( $vendor_id ) { + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_percentage()' ); + return dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_percentage(); } /** * Get vendor wise additional fee * + * @deprecated DOKAN_SINCE Use dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_flat() instead + * * @since 2.9.21 * * @param int $vendor_id @@ -690,29 +321,24 @@ public function get_global_additional_fee() { * @return float|null on failure */ public function get_vendor_wise_additional_fee( $vendor_id ) { - return $this->validate_rate( get_user_meta( $vendor_id, 'dokan_admin_additional_fee', true ) ); + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_flat()' ); + return dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_flat(); } /** - * Get category wise additional fee + * Get vendor wise additional type + * + * @deprecated DOKAN_SINCE Use dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_type() instead * * @since 2.9.21 * - * @param int $product_id + * @param int $vendor_id * * @return float|null on failure */ - public function get_category_wise_additional_fee( $product_id ) { - $terms = get_the_terms( $this->validate_product_id( $product_id ), 'product_cat' ); - - if ( empty( $terms ) ) { - return null; - } - - $term_id = $terms[0]->term_id; - $rate = ! $terms ? null : get_term_meta( $term_id, 'per_category_admin_additional_fee', true ); - - return $this->validate_rate( $rate ); + public function get_vendor_wise_type( $vendor_id ) { + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_type()' ); + return dokan()->vendor->get( $vendor_id )->get_commission_settings()->get_type(); } /** @@ -755,6 +381,8 @@ public function get_earning_from_order_table( $order_id, $context = 'seller' ) { /** * Get shipping fee recipient * + * @deprecated DOKAN_SINCE Use dokan()->fees->get_shipping_fee_recipient() instead + * * @since 2.9.21 * @since 3.4.1 introduced the shipping fee recipient hook * @@ -763,30 +391,16 @@ public function get_earning_from_order_table( $order_id, $context = 'seller' ) { * @return string */ public function get_shipping_fee_recipient( $order ) { - if ( is_numeric( $order ) ) { - $order = wc_get_order( $order ); - } - - if ( ! $order ) { - return new WP_Error( 'invalid-order-object', __( 'Please provide a valid order object.', 'dokan-lite' ) ); - } - - $saved_shipping_recipient = $order->get_meta( 'shipping_fee_recipient', true ); + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->fees->get_shipping_fee_recipient()' ); - if ( $saved_shipping_recipient ) { - $shipping_recipient = $saved_shipping_recipient; - } else { - $shipping_recipient = apply_filters( 'dokan_shipping_fee_recipient', dokan_get_option( 'shipping_fee_recipient', 'dokan_selling', 'seller' ), $order->get_id() ); - $order->update_meta_data( 'shipping_fee_recipient', $shipping_recipient ); - $order->save(); - } - - return $shipping_recipient; + return dokan()->fees->get_shipping_fee_recipient( $order ); } /** * Get tax fee recipient * + * @deprecated DOKAN_SINCE Use dokan()->fees->get_tax_fee_recipient() instead + * * @since 2.9.21 * @since 3.4.1 introduced the tax fee recipient hook * @@ -795,30 +409,16 @@ public function get_shipping_fee_recipient( $order ) { * @return string|WP_Error */ public function get_tax_fee_recipient( $order ) { - if ( is_numeric( $order ) ) { - $order = wc_get_order( $order ); - } - - if ( ! $order ) { - return new WP_Error( 'invalid-order-object', __( 'Please provide a valid order object.', 'dokan-lite' ) ); - } - - $saved_tax_recipient = $order->get_meta( 'tax_fee_recipient', true ); + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->fees->get_tax_fee_recipient()' ); - if ( $saved_tax_recipient ) { - $tax_recipient = $saved_tax_recipient; - } else { - $tax_recipient = apply_filters( 'dokan_tax_fee_recipient', dokan_get_option( 'tax_fee_recipient', 'dokan_selling', 'seller' ), $order->get_id() ); - $order->update_meta_data( 'tax_fee_recipient', $tax_recipient ); - $order->save(); - } - - return $tax_recipient; + return dokan()->fees->get_tax_fee_recipient( $order ); } /** * Get shipping tax fee recipient. * + * @deprecated DOKAN_SINCE Use dokan()->fees->get_shipping_tax_fee_recipient() instead + * * @since 3.7.19 * * @param WC_Order $order Order. @@ -826,25 +426,15 @@ public function get_tax_fee_recipient( $order ) { * @return string */ public function get_shipping_tax_fee_recipient( $order ): string { - // get saved tax recipient - $saved_shipping_tax_recipient = $order->get_meta( 'shipping_tax_fee_recipient', true ); - if ( ! empty( $saved_shipping_tax_recipient ) ) { - return $saved_shipping_tax_recipient; - } - - $default_tax_fee_recipient = $this->get_tax_fee_recipient( $order->get_id() ); // this is needed for backward compatibility - $shipping_tax_recipient = dokan_get_option( 'shipping_tax_fee_recipient', 'dokan_selling', $default_tax_fee_recipient ); - $shipping_tax_recipient = apply_filters( 'dokan_shipping_tax_fee_recipient', $shipping_tax_recipient, $order->get_id() ); - - $order->update_meta_data( 'shipping_tax_fee_recipient', $shipping_tax_recipient, true ); - $order->save(); - - return $shipping_tax_recipient; + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->fees->get_shipping_tax_fee_recipient()' ); + return dokan()->fees->get_shipping_tax_fee_recipient( $order ); } /** * Get total shipping tax refunded for the order. * + * @deprecated DOKAN_SINCE Use dokan()->fees->get_total_shipping_tax_refunded() instead + * * @since 3.7.19 * * @param WC_Order $order Order. @@ -852,23 +442,16 @@ public function get_shipping_tax_fee_recipient( $order ): string { * @return float */ public function get_total_shipping_tax_refunded( WC_Order $order ): float { - $tax_refunded = 0.0; - - foreach ( $order->get_items( 'shipping' ) as $item_id => $item ) { - /** - * @var \WC_Order_Item_Shipping $item Shipping item. - */ - foreach ( $item->get_taxes()['total'] as $tax_id => $tax_amount ) { - $tax_refunded += $order->get_tax_refunded_for_item( $item->get_id(), $tax_id, 'shipping' ); - } - } + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->fees->get_total_shipping_tax_refunded()' ); - return $tax_refunded; + return dokan()->fees->get_total_shipping_tax_refunded( $order ); } /** * Get processing fee * + * @deprecated DOKAN_SINCE Use dokan()->fees->get_processing_fee instead. + * * @since DOKAN_LITE_SINCE * * @param WC_Order $order @@ -876,21 +459,9 @@ public function get_total_shipping_tax_refunded( WC_Order $order ): float { * @return float */ public function get_processing_fee( $order ) { - $processing_fee = 0; - $payment_method = $order->get_payment_method(); - - if ( 'paypal' === $payment_method ) { - $processing_fee = $order->get_meta( 'PayPal Transaction Fee' ); - } elseif ( 'ppec_paypal' === $payment_method && defined( 'PPEC_FEE_META_NAME_NEW' ) ) { - $processing_fee = $order->get_meta( PPEC_FEE_META_NAME_NEW ); - } elseif ( 'ppcp-gateway' === $payment_method && class_exists( PayPalGateway::class ) ) { - $breakdown = $order->get_meta( PayPalGateway::FEES_META_KEY ); - if ( is_array( $breakdown ) && isset( $breakdown['paypal_fee'] ) && is_array( $breakdown['paypal_fee'] ) ) { - $processing_fee = $breakdown['paypal_fee']['value']; - } - } + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'dokan()->fees->get_processing_fee' ); - return apply_filters( 'dokan_get_processing_fee', $processing_fee, $order ); + return dokan()->fees->get_processing_fee( $order ); } /** @@ -916,6 +487,9 @@ public function get_all_order_to_be_processed( $order ) { /** * Calculate commission (commission priority [1.product, 2.category, 3.vendor, 4.global] wise) + * I this function the calculation was written for vendor perspective it is deprecated now it is recomanded to use `get_commission` method it works fo admin perspective. + * + * @deprecated DOKAN_SINCE Use get_commission() instead. * * @since 2.9.21 * @@ -926,30 +500,121 @@ public function get_all_order_to_be_processed( $order ) { * @return float */ public function calculate_commission( $product_id, $product_price, $vendor_id = null ) { - $product_wise_earning = $this->get_product_wise_earning( $product_id, $product_price ); + _deprecated_function( __METHOD__, 'DOKAN_SINCE', 'get_commission' ); + + $commission_data = $this->get_commission( + [ + 'order_item_id' => $this->get_order_item_id(), + 'total_amount' => $product_price, + 'total_quantity' => $this->get_order_qunatity(), + 'product_id' => $product_id, + 'vendor_id' => $vendor_id, + ], + true + ); - if ( ! is_null( $product_wise_earning ) ) { - return $product_wise_earning; - } + $parameters = $commission_data->get_parameters() ?? []; + $percentage = $parameters['percentage'] ?? 0; + $flat = $parameters['flat'] ?? 0; + + return apply_filters( + 'dokan_after_commission_calculation', + $commission_data->get_vendor_earning() ?? 0, + $percentage, $commission_data->get_type() ?? 'none', + $flat, + $product_price, + $this->get_order_id() + ); + } - $category_wise_earning = $this->get_category_wise_earning( $product_id, $product_price ); + /** + * Returns all the commission types that ware in dokan. These types were existed before dokan lite version DOKAN_SINCE + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_legacy_commission_types() { + return [ + 'combine' => __( 'Combine', 'dokan-lite' ), + 'percentage' => __( 'Percentage', 'dokan-lite' ), + 'flat' => __( 'Flat', 'dokan-lite' ), + ]; + } + + /** + * Returns commission (commission priority [1.Order item if exists. 2.product, 3.vendor, 4.global] wise) + * + * @since DOKAN_SINCE + * + * @param array $args { + * Accepted arguments are below. + * + * @type int $order_item_id Order item id. Default ''. Accepted values numbers. + * @type float|int $total_amount The amount on which the commission will be calculated. Default 0. Accepted values numbers. + * Ff you want to calculate for order line item the $total_amount should be total line item amount and + * $total_quantity should be total line item quantity. EX: for product item apple with cost $100 then $total_amount = 500, $total_quantity = 5 + * or if you want to calculate for product price the $total_amount should be the product price and $total_quantity should be 1 + * EX: for product apple with cost $100 then $total_amount = 100, $total_quantity = 1 + * @type int $total_quantity This is the total quantity that represents the $total_amounts item units. Default 1. Accepted values numbers. + * Please read $total_amount doc above to understand clearly. + * @type int $product_id Product id. Default 0. Accepted values numbers. + * @type int $vendor_id Vendor id. Default ''. Accepted values numbers. + * @type int $category_id Product category id. Default 0'. Accepted values numbers. + * } + * @param boolean $auto_save If true, it will save the calculated commission automatically to the given `$order_item_id`. Default 'false`. Accepted values boolean. + * + * @return \WeDevs\Dokan\Commission\Model\Commission + */ + public function get_commission( $args = [], $auto_save = false ) { + $order_item_id = ! empty( $args['order_item_id'] ) ? $args['order_item_id'] : ''; + $total_amount = ! empty( $args['total_amount'] ) ? $args['total_amount'] : 0; + $total_quantity = ! empty( $args['total_quantity'] ) ? $args['total_quantity'] : 1; + $product_id = ! empty( $args['product_id'] ) ? $args['product_id'] : 0; + $vendor_id = ! empty( $args['vendor_id'] ) ? $args['vendor_id'] : ''; + $category_id = ! empty( $args['category_id'] ) ? $args['category_id'] : 0; - if ( ! is_null( $category_wise_earning ) ) { - return $category_wise_earning; + // Category commission will not applicable if 'Product Category Selection' is set as 'Multiple' in Dokan settings. + if ( ! empty( $product_id ) && empty( $category_id ) ) { + $product_categories = Helper::get_saved_products_category( $product_id ); + $chosen_categories = $product_categories['chosen_cat']; + $category_id = reset( $chosen_categories ); + $category_id = $category_id ? $category_id : 0; } - $vendor_wise_earning = $this->get_vendor_wise_earning( $vendor_id, $product_price ); + if ( ! empty( $product_id ) && empty( $total_amount ) ) { + $product = dokan()->product->get( $product_id ); - if ( ! is_null( $vendor_wise_earning ) ) { - return $vendor_wise_earning; + // If product price is empty the setting the price as 0 + $total_amount = $product && $product->get_price() && ! empty( $product->get_price() ) ? $product->get_price() : 0; } - $global_earning = $this->get_global_earning( $product_price ); + $order_item_strategy = new OrderItem( $order_item_id, $total_amount, $total_quantity ); - if ( ! is_null( $global_earning ) ) { - return $global_earning; + $strategies = [ + $order_item_strategy, + new Product( $product_id ), + new Vendor( $vendor_id, $category_id ), + new GlobalStrategy( $category_id ), + new DefaultStrategy(), + ]; + + $context = new Calculator( $strategies ); + $commission_data = $context->calculate_commission( $total_amount, $total_quantity ); + + if ( ! empty( $order_item_id ) && $auto_save && $commission_data->get_source() !== $order_item_strategy::SOURCE ) { + $parameters = $commission_data->get_parameters() ?? []; + $percentage = $parameters['percentage'] ?? 0; + $flat = $parameters['flat'] ?? 0; + + $order_item_strategy->save_line_item_commission_to_meta( + $commission_data->get_type() ?? DefaultSetting::TYPE, + $percentage, + $flat, + $commission_data->get_data() + ); } - return $product_price; + return $commission_data; } } diff --git a/includes/Commission/Calculator.php b/includes/Commission/Calculator.php new file mode 100644 index 0000000000..acfb0c2464 --- /dev/null +++ b/includes/Commission/Calculator.php @@ -0,0 +1,80 @@ +strategies = $strategies; + } + + /** + * Returns applied commission data + * + * @since DOKAN_SINCE + * + * @param int|float $total_amount + * @param int $total_quantity + * + * @return \WeDevs\Dokan\Commission\Model\Commission + */ + public function calculate_commission( $total_amount, $total_quantity = 1 ): Commission { + if ( ! is_numeric( $total_quantity ) || $total_quantity < 1 ) { + $total_quantity = 1; + } + + if ( ! is_numeric( $total_amount ) ) { + $total_quantity = 0; + } + + $commission_data = new Commission(); + $commission_data->set_vendor_earning( $total_amount ) + ->set_total_quantity( $total_quantity ) + ->set_total_amount( $total_amount ); + + foreach ( $this->strategies as $strategy ) { + $formula = $strategy->create_formula(); + if ( $formula->is_applicable() ) { + $formula->set_amount( $total_amount ) + ->set_quantity( $total_quantity ) + ->calculate(); + + $commission_data->set_source( $strategy->get_source() ) + ->set_per_item_admin_commission( $formula->get_per_item_admin_commission() ) + ->set_admin_commission( $formula->get_admin_commission() ) + ->set_vendor_earning( $formula->get_vendor_earning() ) + ->set_total_quantity( $formula->get_items_total_quantity() ) + ->set_total_amount( $total_amount ) + ->set_type( $formula->get_source() ) + ->set_parameters( $formula->get_parameters() ); + + return $commission_data; + } + } + + // If no commission is defined at any level. + return $commission_data; + } +} diff --git a/includes/Commission/Formula/AbstractFormula.php b/includes/Commission/Formula/AbstractFormula.php new file mode 100644 index 0000000000..6bc7e55903 --- /dev/null +++ b/includes/Commission/Formula/AbstractFormula.php @@ -0,0 +1,189 @@ +settings = $setting; + + return $this; + } + + /** + * Returns the commission settings. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_settings(): Setting { + return $this->settings; + } + + /** + * Sets the total amount on which the commission will be calculated. + * + * @param float|int $amount + * + * @since DOKAN_SINCE + * + * @return AbstractFormula + */ + public function set_amount( $amount ): AbstractFormula { + $this->total_amount = $amount; + + return $this; + } + + /** + * Sets the total quantity on which the commission will be calculated. + * + * @param int $quantity + * + * @since DOKAN_SINCE + * + * @return AbstractFormula + */ + public function set_quantity( $quantity ): AbstractFormula { + $this->total_quantity = $quantity; + + return $this; + } + + /** + * Returns the total amount on which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @return float|int + */ + public function get_amount() { + return $this->total_amount; + } + + /** + * Returns the total quantity on which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_quantity(): int { + return $this->total_quantity; + } + + /** + * Calculate the commission here and set the commission values. + * + * @since DOKAN_SINCE + * + * @param $total_amount + * + * @param $total_quantity + * + * @return void + */ + abstract public function calculate(); + + /** + * Returns admin commission. + * + * @since DOKAN_SINCE + * + * @return float + */ + abstract public function get_admin_commission(): float; + + /** + * Returns vendor earning. + * + * @since DOKAN_SINCE + * + * @return float + */ + abstract public function get_vendor_earning(): float; + + /** + * Returns applied commission parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + abstract public function get_parameters(): array; + + /** + * Returns applied commission source. + * + * @since DOKAN_SINCE + * + * @return string + */ + abstract public function get_source(): string; + + /** + * Returns per item admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + abstract public function get_per_item_admin_commission(): float; + + /** + * Returns the quantity for which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + abstract public function get_items_total_quantity(): int; + + /** + * Returns if the commission is applicable or not. + * + * @since DOKAN_SINCE + * + * @return bool + */ + abstract public function is_applicable(): bool; +} diff --git a/includes/Commission/Formula/CategoryBased.php b/includes/Commission/Formula/CategoryBased.php new file mode 100644 index 0000000000..5f12489ef9 --- /dev/null +++ b/includes/Commission/Formula/CategoryBased.php @@ -0,0 +1,354 @@ +set_settings( $this->get_valid_commission_settings( $settings ) ); + $this->fixed_formula = new Fixed( $this->fixed_commission_setting ); + } + + /** + * Calculating the category commission. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function calculate() { + $this->set_quantity( max( $this->get_quantity(), 1 ) ); + + if ( $this->is_applicable() && $this->fixed_formula->is_applicable() ) { + $this->fixed_formula->set_amount( $this->get_amount() ); + $this->fixed_formula->set_quantity( $this->get_quantity() ); + $this->fixed_formula->calculate(); + + $this->per_item_admin_commission = $this->fixed_formula->get_per_item_admin_commission(); + $this->admin_commission = $this->fixed_formula->get_admin_commission(); + $this->vendor_earning = $this->fixed_formula->get_vendor_earning(); + } else { + $this->per_item_admin_commission = 0; + $this->admin_commission = 0; + $this->vendor_earning = $this->get_amount(); + } + + $this->items_total_quantity = $this->get_quantity(); + } + + /** + * Returns calculated commissions meta data. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_meta_data(): array { + return $this->meta_data; + } + + /** + * Sets category commission meta data. + * + * @since DOKAN_SINCE + * + * @param array $meta_data + * + * @return \WeDevs\Dokan\Commission\Formula\CategoryBased + */ + public function set_meta_data( array $meta_data ): CategoryBased { + $this->meta_data = $meta_data; + + return $this; + } + + /** + * Returns type. + * + * @since DOKAN_SINCE + * + * @return mixed + */ + public function get_type() { + return $this->type; + } + + /** + * Get commission date parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_parameters(): array { + $parameters = $this->fixed_formula->get_parameters(); + + $parameters['category_id'] = $this->get_settings()->get_category_id(); + $parameters['meta_data'] = $this->get_settings()->get_meta_data(); + + return $parameters; + } + + /** + * Returns commission source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns if a category commission is applicable or not. + * + * @since DOKAN_SINCE + * + * @return bool + */ + public function is_applicable(): bool { + if ( $this->is_valid_commission_type() && $this->is_valid_commission_data() ) { + // Changing the type here another wise fixed commission is applicable will always be false, we will set back the type to category later. + $this->set_settings( $this->get_settings()->set_type( Fixed::SOURCE ) ); + $applicable = $this->fixed_formula->is_applicable(); + + // Setting the commission type back to category based. + $this->set_settings( $this->get_settings()->set_type( self::SOURCE ) ); + return $applicable; + } + + return false; + } + + /** + * Returns true if commission type is valid. + * + * @since DOKAN_SINCE + * + * @return bool + */ + protected function is_valid_commission_type(): bool { + return $this->get_settings()->get_type() === $this->get_source(); + } + + /** + * Returns if saved commission data is valid to be applied. + * + * @since DOKAN_SINCE + * + * @return bool + */ + protected function is_valid_commission_data(): bool { + $valid_category_id = is_numeric( $this->get_settings()->get_category_id() ); + $has_category_setting = isset( $this->get_settings()->get_category_commissions()['items'][ $this->get_settings()->get_category_id() ] ); + $category_flat_value = $has_category_setting && isset( $this->get_settings()->get_category_commissions()['items'][ $this->get_settings()->get_category_id() ]['flat'] ) + ? $this->get_settings()->get_category_commissions()['items'][ $this->get_settings()->get_category_id() ]['flat'] + : ''; + $category_percentage_value = $has_category_setting && isset( $this->get_settings()->get_category_commissions()['items'][ $this->get_settings()->get_category_id() ]['percentage'] ) + ? $this->get_settings()->get_category_commissions()['items'][ $this->get_settings()->get_category_id() ]['percentage'] + : ''; + + $has_all_setting = isset( $this->get_settings()->get_category_commissions()['all'] ); + $has_all_flat_setting = $has_all_setting && isset( $this->get_settings()->get_category_commissions()['all']['flat'] ) ? $this->get_settings()->get_category_commissions()['all']['flat'] : ''; + $has_all_percentage_setting = $has_all_setting && isset( $this->get_settings()->get_category_commissions()['all']['percentage'] ) ? $this->get_settings()->get_category_commissions()['all']['percentage'] : ''; + + if ( + $valid_category_id && + $has_category_setting && + ( is_numeric( $category_flat_value ) || is_numeric( $category_percentage_value ) ) + ) { + return true; + } elseif ( + $valid_category_id && + $has_category_setting && + ( ! is_numeric( $category_flat_value ) && ! is_numeric( $category_percentage_value ) ) + ) { + return false; + } elseif ( $has_all_setting && ( is_numeric( $has_all_flat_setting ) || is_numeric( $has_all_percentage_setting ) ) ) { + return true; + } + + return false; + } + + /** + * Validates and returns commission. + * + * @since DOKAN_SINCE + * + * @param Setting $setting + * + * @return Setting + */ + protected function get_valid_commission_settings( Setting $setting ): Setting { + $this->set_settings( $setting ); + + $this->fixed_commission_setting = new Setting(); + $this->fixed_commission_setting->set_type( Fixed::SOURCE ) + ->set_flat( $this->get_settings()->get_flat() ) + ->set_percentage( $this->get_settings()->get_percentage() ) + ->set_category_id( $this->get_settings()->get_category_id() ) + ->set_category_commissions( $this->get_settings()->get_category_commissions() ) + ->set_meta_data( $this->get_settings()->get_meta_data() ); + + if ( ! $this->is_valid_commission_data() ) { + return $setting; + } + + // $validated_setting = new Setting(); + $commissions = $setting->get_category_commissions(); + if ( is_numeric( $setting->get_category_id() ) && isset( $setting->get_category_commissions()['items'][ $setting->get_category_id() ] ) ) { + $items = $commissions['items']; + $item = $items[ $setting->get_category_id() ]; + + $this->fixed_commission_setting->set_flat( isset( $item['flat'] ) ? $item['flat'] : '' ); + $this->fixed_commission_setting->set_percentage( isset( $item['percentage'] ) ? $item['percentage'] : '' ); + $this->fixed_commission_setting->set_category_commissions( $commissions ); + } elseif ( isset( $setting->get_category_commissions()['all'] ) && ( is_numeric( $setting->get_category_commissions()['all']['flat'] ) || is_numeric( $setting->get_category_commissions()['all']['percentage'] ) ) ) { + $all = $commissions['all']; + + $this->fixed_commission_setting->set_flat( isset( $all['flat'] ) ? $all['flat'] : '' ); + $this->fixed_commission_setting->set_percentage( isset( $all['percentage'] ) ? $all['percentage'] : '' ); + $this->fixed_commission_setting->set_category_commissions( $commissions ); + } + + return $setting; + } + + /** + * Returns admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_admin_commission(): float { + return $this->admin_commission; + } + + /** + * Returns vendor earning amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_vendor_earning(): float { + return $this->vendor_earning; + } + + + /** + * Returns per item admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_per_item_admin_commission(): float { + return dokan()->commission->validate_rate( $this->per_item_admin_commission ); + } + + /** + * Returns the quantity on which the commission has been calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_items_total_quantity(): int { + return $this->items_total_quantity; + } +} diff --git a/includes/Commission/Formula/Combine.php b/includes/Commission/Formula/Combine.php new file mode 100644 index 0000000000..a7b435a07a --- /dev/null +++ b/includes/Commission/Formula/Combine.php @@ -0,0 +1,198 @@ +set_settings( $settings ); + } + + /** + * Calculation is doing here. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function calculate() { + $percent_commission = $this->get_amount() * ( dokan()->commission->validate_rate( $this->get_settings()->get_percentage() ) / 100 ); + $commission = (float) dokan()->commission->validate_rate( $this->get_settings()->get_flat() ) + $percent_commission; + + $per_item_flat = dokan()->commission->validate_rate( $this->get_settings()->get_flat() ) / $this->get_quantity(); + $per_item_percentage = $percent_commission / $this->get_quantity(); + + $this->admin_commission = $commission; + $this->per_item_admin_commission = $per_item_flat + $per_item_percentage; + + if ( $this->get_per_item_admin_commission() > $this->get_amount() ) { + $this->per_item_admin_commission = $this->get_amount(); + } + + if ( $this->get_admin_commission() > $this->get_amount() ) { + $this->admin_commission = $this->get_amount(); + } + + $this->vendor_earning = $this->get_amount() - $this->admin_commission; + $this->items_total_quantity = $this->get_quantity(); + } + + /** + * Commission calculation parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_parameters(): array { + return [ + 'flat' => $this->get_settings()->get_flat(), + 'percentage' => $this->get_settings()->get_percentage(), + 'meta_data' => $this->get_settings()->get_meta_data(), + ]; + } + + /** + * Returns the combine commission surce text. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns if the combine commission is applicable or not based on data. + * + * @since DOKAN_SINCE + * + * @return bool + */ + public function is_applicable(): bool { + return $this->is_valid_commission_type() && $this->is_valid_commission_data(); + } + + /** + * Returns if the commission type data is valid. + * + * @since DOKAN_SINCE + * + * @return bool + */ + protected function is_valid_commission_type(): bool { + $legacy_types = dokan()->commission->get_legacy_commission_types(); + + $all_types = array_keys( $legacy_types ); + + return in_array( $this->get_settings()->get_type(), $all_types, true ) || $this->get_settings()->get_type() === self::SOURCE; + } + + /** + * Returns if commission is valid. + * + * @since DOKAN_SINCE + * + * @return bool + */ + protected function is_valid_commission_data(): bool { + return is_numeric( $this->get_settings()->get_flat() ) || is_numeric( $this->get_settings()->get_percentage() ); + } + + /** + * Returns the admin commission + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_admin_commission(): float { + return dokan()->commission->validate_rate( $this->admin_commission ); + } + + /** + * Returns the vendors earning. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_vendor_earning(): float { + return dokan()->commission->validate_rate( $this->vendor_earning ); + } + + /** + * Returns per item admin commission. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_per_item_admin_commission(): float { + return dokan()->commission->validate_rate( $this->per_item_admin_commission ); + } + + /** + * Returns the quantity on which the commission is calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_items_total_quantity(): int { + return $this->items_total_quantity; + } +} diff --git a/includes/Commission/Formula/Fixed.php b/includes/Commission/Formula/Fixed.php new file mode 100644 index 0000000000..0efbf8edbe --- /dev/null +++ b/includes/Commission/Formula/Fixed.php @@ -0,0 +1,226 @@ +set_settings( $settings ); + + $this->flat_calculator = new Flat( $this->get_settings() ); + $this->percentage_calculator = new Percentage( $this->get_settings() ); + } + + /** + * Calculating the fixed commission. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function calculate() { + $this->set_quantity( max( $this->get_quantity(), 1 ) ); + + if ( $this->flat_calculator->is_applicable() ) { + $this->flat_calculator->set_amount( $this->get_amount() ); + $this->flat_calculator->set_quantity( $this->get_quantity() ); + $this->flat_calculator->calculate(); + + $this->per_item_admin_commission += $this->flat_calculator->get_per_item_admin_commission(); + $this->admin_commission += $this->flat_calculator->get_admin_commission(); + } + + if ( $this->percentage_calculator->is_applicable() ) { + $this->percentage_calculator->set_amount( $this->get_amount() ); + $this->percentage_calculator->set_quantity( $this->get_quantity() ); + $this->percentage_calculator->calculate(); + + $this->per_item_admin_commission += $this->percentage_calculator->get_per_item_admin_commission(); + $this->admin_commission += $this->percentage_calculator->get_admin_commission(); + } + + if ( $this->get_per_item_admin_commission() > $this->get_amount() ) { + $this->per_item_admin_commission = $this->get_amount(); + } + + if ( $this->get_admin_commission() > $this->get_amount() ) { + $this->admin_commission = $this->get_amount(); + } + + $this->vendor_earning = $this->get_amount() - $this->get_admin_commission(); + $this->items_total_quantity = $this->get_quantity(); + } + + /** + * Get commission date parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_parameters(): array { + return [ + 'flat' => $this->get_settings()->get_flat(), + 'percentage' => $this->get_settings()->get_percentage(), + 'meta_data' => $this->get_settings()->get_meta_data(), + ]; + } + + /** + * Returns commission source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns if a fixed commission is applicable or not. + * + * @since DOKAN_SINCE + * + * @return bool + */ + public function is_applicable(): bool { + return $this->is_valid_commission_type() && $this->is_valid_commission_data(); + } + + /** + * Returns true if commission type is valid. + * + * @since DOKAN_SINCE + * + * @return bool + */ + protected function is_valid_commission_type(): bool { + $legacy_types = dokan()->commission->get_legacy_commission_types(); + + $all_types = array_keys( $legacy_types ); + + return in_array( $this->get_settings()->get_type(), $all_types, true ) || $this->get_settings()->get_type() === self::SOURCE; + } + + /** + * Returns if saved commission data is valid to be applied. + * + * @since DOKAN_SINCE + * + * @return bool + */ + protected function is_valid_commission_data(): bool { + return is_numeric( $this->get_settings()->get_flat() ) || is_numeric( $this->get_settings()->get_percentage() ); + } + + /** + * Returns admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_admin_commission(): float { + return dokan()->commission->validate_rate( $this->admin_commission ); + } + + /** + * Returns vendor earning amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_vendor_earning(): float { + return dokan()->commission->validate_rate( $this->vendor_earning ); + } + + /** + * Returns per item admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_per_item_admin_commission(): float { + return dokan()->commission->validate_rate( $this->per_item_admin_commission ); + } + + /** + * Returns the quantity on which the commission has been calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_items_total_quantity(): int { + return $this->items_total_quantity; + } +} diff --git a/includes/Commission/Formula/Flat.php b/includes/Commission/Formula/Flat.php new file mode 100644 index 0000000000..3b443ccce8 --- /dev/null +++ b/includes/Commission/Formula/Flat.php @@ -0,0 +1,184 @@ +set_settings( $settings ); + } + + /** + * Calculating the flat commission. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function calculate() { + $this->set_quantity( max( $this->get_quantity(), 1 ) ); + + if ( $this->is_applicable() ) { + $this->per_item_admin_commission = dokan()->commission->validate_rate( $this->get_settings()->get_flat() ); + } + + if ( $this->per_item_admin_commission > $this->get_amount() ) { + $this->per_item_admin_commission = $this->get_amount(); + } + + $this->flat_commission = $this->per_item_admin_commission; + if ( (int) $this->get_quantity() > 1 ) { + $this->flat_commission = $this->per_item_admin_commission * apply_filters( 'dokan_commission_multiply_by_order_quantity', $this->get_quantity() ); + } + + $this->admin_commission = $this->flat_commission; + + if ( $this->admin_commission > $this->get_amount() ) { + $this->admin_commission = $this->get_amount(); + } + + $this->vendor_earning = $this->get_amount() - $this->admin_commission; + $this->items_total_quantity = $this->get_quantity(); + } + + /** + * Get commission date parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_parameters(): array { + return [ + 'flat' => $this->get_settings()->get_flat(), + 'meta_data' => $this->get_settings()->get_meta_data(), + ]; + } + + /** + * Returns commission source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns if a flat commission is applicable or not. + * + * @since DOKAN_SINCE + * + * @return bool + */ + public function is_applicable(): bool { + return is_numeric( $this->get_settings()->get_flat() ); + } + + /** + * Returns admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_admin_commission(): float { + return $this->admin_commission; + } + + /** + * Returns vendor earning amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_vendor_earning(): float { + return $this->vendor_earning; + } + + /** + * Returns per item admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_per_item_admin_commission(): float { + return dokan()->commission->validate_rate( $this->per_item_admin_commission ); + } + + /** + * Returns the quantity on which the commission has been calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_items_total_quantity(): int { + return $this->items_total_quantity; + } +} diff --git a/includes/Commission/Formula/Percentage.php b/includes/Commission/Formula/Percentage.php new file mode 100644 index 0000000000..07f4f8e0aa --- /dev/null +++ b/includes/Commission/Formula/Percentage.php @@ -0,0 +1,159 @@ +set_settings( $settings ); + } + + /** + * Class constructor. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function calculate() { + if ( $this->is_applicable() ) { + $this->admin_commission = ( $this->get_amount() * dokan()->commission->validate_rate( $this->get_settings()->get_percentage() ) ) / 100; + } + + $this->per_item_admin_commission = $this->admin_commission / $this->get_quantity(); + $this->vendor_earning = $this->get_amount() - $this->admin_commission; + + // Admin will get 100 percent if commission rate > 100 + if ( $this->get_settings()->get_percentage() > 100 ) { + $this->admin_commission = $this->get_amount(); + $this->vendor_earning = 0; + } + + $this->items_total_quantity = $this->get_quantity(); + } + + /** + * Get commission date parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_parameters(): array { + return [ + 'percentage' => $this->get_settings()->get_percentage(), + 'meta_data' => $this->get_settings()->get_meta_data(), + ]; + } + + /** + * Returns commission source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns if a percentage commission is applicable or not. + * + * @since DOKAN_SINCE + * + * @return bool + */ + public function is_applicable(): bool { + return is_numeric( $this->get_settings()->get_percentage() ); + } + + /** + * Returns admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_admin_commission(): float { + return dokan()->commission->validate_rate( $this->admin_commission ); + } + + /** + * Returns vendor earning amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_vendor_earning(): float { + return dokan()->commission->validate_rate( $this->vendor_earning ); + } + + /** + * Returns per item admin commission amount. + * + * @since DOKAN_SINCE + * + * @return float + */ + public function get_per_item_admin_commission(): float { + return dokan()->commission->validate_rate( $this->per_item_admin_commission ) ?? 0; + } + + /** + * Returns the quantity on which the commission has been calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_items_total_quantity(): int { + return $this->items_total_quantity; + } +} diff --git a/includes/Commission/FormulaFactory.php b/includes/Commission/FormulaFactory.php new file mode 100644 index 0000000000..16f45cff26 --- /dev/null +++ b/includes/Commission/FormulaFactory.php @@ -0,0 +1,48 @@ +get_type() ) { + case Flat::SOURCE: + // In Dokan before DOKAN_SINCE version if the commission type was flat the flat value used to be saved in the percentage key, that is why we are passing the percentage value. + return new Flat( $settings ); + case Percentage::SOURCE: + return new Percentage( $settings ); + case Combine::SOURCE: // Assuming 'combine' implies a combination of flat + percentage + return new Combine( $settings ); + case Fixed::SOURCE: + return new Fixed( $settings ); + case CategoryBased::SOURCE: + return new CategoryBased( $settings ); + default: + $default_setting = new DefaultSetting(); + return new Percentage( $default_setting->get() ); + } + } +} diff --git a/includes/Commission/Model/Commission.php b/includes/Commission/Model/Commission.php new file mode 100644 index 0000000000..886fc304b1 --- /dev/null +++ b/includes/Commission/Model/Commission.php @@ -0,0 +1,308 @@ +source; + } + + /** + * Sets commission source. + * + * @since DOKAN_SINCE + * + * @param string $source + * + * @return Commission + */ + public function set_source( string $source ): Commission { + $this->source = $source; + + return $this; + } + + /** + * Returns per item admin commission. + * + * @since DOKAN_SINCE + * + * @return int|float + */ + public function get_per_item_admin_commission() { + return $this->per_item_admin_commission; + } + + /** + * Sets per item admin commission. + * + * @since DOKAN_SINCE + * + * @param int|float $per_item_admin_commission + * + * @return Commission + */ + public function set_per_item_admin_commission( $per_item_admin_commission ): Commission { + $this->per_item_admin_commission = $per_item_admin_commission; + + return $this; + } + + /** + * Returns the admin commission amount. + * + * @since DOKAN_SINCE + * + * @return int|float + */ + public function get_admin_commission() { + return $this->admin_commission; + } + + /** + * Sets admin commission amount. + * + * @since DOKAN_SINCE + * + * @param $admin_commission + * + * @return Commission + */ + public function set_admin_commission( $admin_commission ): Commission { + $this->admin_commission = $admin_commission; + + return $this; + } + + /** + * Returns vendor earning. + * + * @since DOKAN_SINCE + * + * @return int|float + */ + public function get_vendor_earning() { + return $this->vendor_earning; + } + + /** + * Sets vendor earning.. + * + * @since DOKAN_SINCE + * + * @param int|float $vendor_earning + * + * @return Commission + */ + public function set_vendor_earning( $vendor_earning ): Commission { + $this->vendor_earning = $vendor_earning; + + return $this; + } + + /** + * Returns the quantity on which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_total_quantity(): int { + return $this->total_quantity; + } + + /** + * Sets the total quantity on which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @param int $total_quantity + * + * @return Commission + */ + public function set_total_quantity( int $total_quantity ): Commission { + $this->total_quantity = $total_quantity; + + return $this; + } + + /** + * Returns the total amount on which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_total_amount() { + return $this->total_amount; + } + + /** + * Sets the total amount on which the commission will be calculated. + * + * @since DOKAN_SINCE + * + * @param int|float $total_amount + * + * @return Commission + */ + public function set_total_amount( $total_amount ): Commission { + $this->total_amount = $total_amount; + + return $this; + } + + /** + * Returns the commission type. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_type(): string { + return $this->type; + } + + /** + * Sets the commission type + * + * @param string $type + * + * @return Commission + */ + public function set_type( string $type ): Commission { + $this->type = $type; + + return $this; + } + + /** + * Returns applied commission parameters. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_parameters(): array { + return $this->parameters; + } + + /** + * Sets commission parameters. + * + * @since DOKAN_SINCE + * + * @param array $parameters + * + * @return Commission + */ + public function set_parameters( array $parameters ): Commission { + $this->parameters = $parameters; + + return $this; + } + + /** + * Returns commission data as array. + * + * @since DOKAN_SINCE + * + * @return array + */ + public function get_data(): array { + return [ + 'source' => $this->get_source(), + 'per_item_admin_commission' => $this->get_per_item_admin_commission(), + 'admin_commission' => $this->get_admin_commission(), + 'vendor_earning' => $this->get_vendor_earning(), + 'total_quantity' => $this->get_total_quantity(), + 'total_amount' => $this->get_total_amount(), + 'type' => $this->get_type(), + 'parameters' => $this->get_parameters(), + ]; + } +} diff --git a/includes/Commission/Model/Setting.php b/includes/Commission/Model/Setting.php new file mode 100644 index 0000000000..5a078bbf70 --- /dev/null +++ b/includes/Commission/Model/Setting.php @@ -0,0 +1,217 @@ +meta_data; + } + + /** + * Sets the commission meta data. + * + * @since DOKAN_SINCE + * + * @param array $meta_data + * + * @return $this + */ + public function set_meta_data( array $meta_data ): Setting { + $this->meta_data = $meta_data; + + return $this; + } + + /** + * Sets the commission type. + * + * @since DOKAN_SINCE + * + * @param mixed|string $type + * + * @return $this + */ + public function set_type( $type ): Setting { + $this->type = $type; + + return $this; + } + + /** + * Sets the flat commissin amount. + * + * @since DOKAN_SINCE + * + * @param mixed|string $flat + * + * @return $this + */ + public function set_flat( $flat ): Setting { + $this->flat = $flat; + + return $this; + } + + /** + * Sets the percentage amount. + * + * @since DOKAN_SINCE + * + * @param mixed|string $percentage + * + * @return $this + */ + public function set_percentage( $percentage ): Setting { + $this->percentage = $percentage; + + return $this; + } + + /** + * Sets the category id. + * + * @since DOKAN_SINCE + * + * @param mixed|string $category_id + * + * @return $this + */ + public function set_category_id( $category_id ): Setting { + $this->category_id = $category_id; + + return $this; + } + + /** + * Sets the category commission data. + * + * @since DOKAN_SINCE. + * + * @param array|mixed $category_commissions + * + * @return $this + */ + public function set_category_commissions( $category_commissions ): Setting { + $this->category_commissions = $category_commissions; + + return $this; + } + + /** + * Sets the commission type. + * + * @since DOKAN_SINCE + * + * @return mixed|string|null + */ + public function get_type() { + return $this->type; + } + + /** + * Returns the flat amount. + * + * @since DOKAN_SINCE + * + * @return mixed|string + */ + public function get_flat() { + return $this->flat; + } + + /** + * Returns the percentage amount. + * + * @since DOKAN_SINCE + * + * @return mixed|string + */ + public function get_percentage() { + return $this->percentage; + } + + /** + * Returns the category commission data. + * + * @since DOKAN_SINCE + * + * @return array|mixed|null + */ + public function get_category_commissions() { + return $this->category_commissions; + } + + /** + * Returns the category id + * + * @since DOKAN_SINCE + * + * @return array|mixed|null + */ + public function get_category_id() { + return $this->category_id; + } +} diff --git a/includes/Commission/Settings/Builder.php b/includes/Commission/Settings/Builder.php new file mode 100644 index 0000000000..85c15fc992 --- /dev/null +++ b/includes/Commission/Settings/Builder.php @@ -0,0 +1,41 @@ +set_type( self::TYPE ); + + return $setting; + } + + /** + * Saves and returns default setting + * + * @since DOKAN_SINCE + * + * @param array $setting + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save( array $setting ): Setting { + return $this->get(); + } +} diff --git a/includes/Commission/Settings/GlobalSetting.php b/includes/Commission/Settings/GlobalSetting.php new file mode 100644 index 0000000000..bfd17ce869 --- /dev/null +++ b/includes/Commission/Settings/GlobalSetting.php @@ -0,0 +1,78 @@ +category_id = $category_id; + } + + /** + * Returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get(): Setting { + $percentage = dokan_get_option( 'admin_percentage', 'dokan_selling', '' ); + $type = dokan_get_option( 'commission_type', 'dokan_selling', '' ); + $flat = dokan_get_option( 'additional_fee', 'dokan_selling', '' ); + $category_commissions = dokan_get_option( 'commission_category_based_values', 'dokan_selling', [] ); + + $settings = new Setting(); + $settings->set_type( $type ) + ->set_flat( $flat ) + ->set_percentage( $percentage ) + ->set_category_commissions( $category_commissions ) + ->set_category_id( $this->category_id ); + + return $settings; + } + + /** + * Saves and returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @param array $setting { + * + * @type string $percentage + * @type string $type + * @type string $flat + * @type array $category_commissions + * } + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save( array $setting ): Setting { + $options = get_option( 'dokan_selling', [] ); + $options['commission_type'] = isset( $setting['type'] ) ? $setting['type'] : ''; + $options['admin_percentage'] = isset( $setting['percentage'] ) ? $setting['percentage'] : ''; + $options['additional_fee'] = isset( $setting['flat'] ) ? $setting['flat'] : ''; + $options['commission_category_based_values'] = isset( $setting['category_commissions'] ) ? $setting['category_commissions'] : []; + + update_option( 'dokan_selling', $options ); + + return $this->get(); + } +} diff --git a/includes/Commission/Settings/InterfaceSetting.php b/includes/Commission/Settings/InterfaceSetting.php new file mode 100644 index 0000000000..6e8fa5d8a3 --- /dev/null +++ b/includes/Commission/Settings/InterfaceSetting.php @@ -0,0 +1,33 @@ +order_item_id = $data['id']; + $this->product_price_to_calculate_commission = $data['price']; + } + + /** + * Rrturns order item commission settings. + * + * @since DOKAN_SINCE + * + * @throws \Exception + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get(): Setting { + $commission_percentage = ''; + $commission_type = ''; + $additional_flat = ''; + $commission_meta = []; + + if ( ! empty( $this->order_item_id ) ) { + $commission_percentage = wc_get_order_item_meta( $this->order_item_id, '_dokan_commission_rate', true ) ?? ''; + $commission_type = wc_get_order_item_meta( $this->order_item_id, '_dokan_commission_type', true ) ?? ''; + $additional_flat = wc_get_order_item_meta( $this->order_item_id, '_dokan_additional_fee', true ) ?? ''; + $commission_meta = wc_get_order_item_meta( $this->order_item_id, 'dokan_commission_meta', true ); + + $commission_meta = empty( $commission_meta ) ? [] : $commission_meta; + } + + /** + * If `_dokan_item_total` returns `non-falsy` value that means, the request comes from the `order refund request`. + * So modify `additional_fee` to the correct amount to get refunded. (additional_fee/item_total)*product_price. + * Where `product_price` means item_total - refunded_total_for_item. + * + * To understand clearly, how and when these codes work and how dokan commission works, you can also go through dokan-lite previous codes as provided below. + * + * @see https://github.com/getdokan/dokan/blob/28888e6824d96747ed65004fbd6de80d0eee5161/includes/Commission.php#L629 + * @see https://github.com/getdokan/dokan/blob/28888e6824d96747ed65004fbd6de80d0eee5161/includes/Commission.php#L567-L653 + * @see https://github.com/getdokan/dokan/blob/28888e6824d96747ed65004fbd6de80d0eee5161/includes/Commission.php + */ + $order_id = wc_get_order_id_by_order_item_id( $this->order_item_id ); + + if ( $order_id && OrderUtil::is_hpos_enabled() ) { + $order = dokan()->order->get( $order_id ); + $item_total = $order->get_meta( '_dokan_item_total' ); + } else { + $item_total = get_post_meta( $order_id, '_dokan_item_total', true ); + } + + $product_price = (float) wc_format_decimal( $this->product_price_to_calculate_commission ); + if ( $order_id && $item_total ) { + $additional_flat = ( $additional_flat / $item_total ) * $product_price; + } + + $settings = new Setting(); + $settings->set_type( $commission_type ) + ->set_flat( $additional_flat ) + ->set_percentage( $commission_percentage ) + ->set_meta_data( $commission_meta ); + + if ( $commission_type === CategoryBased::SOURCE && isset( $commission_meta['parameters']['category_id'] ) ) { + $settings->set_category_id( $commission_meta['parameters']['category_id'] ); + $settings->set_category_commissions( + [ + 'all' => [], + 'items' => [ + $settings->get_category_id() => [ + 'flat' => $settings->get_flat(), + 'percentage' => $settings->get_percentage(), + ], + ], + ] + ); + } else { + $settings->set_category_commissions( + [ + 'all' => [ + 'flat' => $settings->get_flat(), + 'percentage' => $settings->get_percentage(), + ], + 'items' => [], + ] + ); + } + + return $settings; + } + + /** + * Saves order item commission settings. + * + * @since DOKAN_SINCE + * + * @param array $setting + * + * @throws \Exception + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save( array $setting ): Setting { + $percentage = isset( $setting['percentage'] ) ? $setting['percentage'] : ''; + $type = isset( $setting['type'] ) ? $setting['type'] : ''; + $flat = isset( $setting['flat'] ) ? $setting['flat'] : ''; + $meta_data = isset( $setting['meta_data'] ) ? $setting['meta_data'] : []; + + wc_add_order_item_meta( $this->order_item_id, '_dokan_commission_type', $type ); + wc_add_order_item_meta( $this->order_item_id, '_dokan_commission_rate', $percentage ); + wc_add_order_item_meta( $this->order_item_id, '_dokan_additional_fee', $flat ); + wc_add_order_item_meta( $this->order_item_id, 'dokan_commission_meta', $meta_data ); + + return $this->get(); + } +} diff --git a/includes/Commission/Settings/Product.php b/includes/Commission/Settings/Product.php new file mode 100644 index 0000000000..e3af5b0309 --- /dev/null +++ b/includes/Commission/Settings/Product.php @@ -0,0 +1,89 @@ +product = dokan()->product->get( $product_id ); + + if ( $this->product && $this->product->is_type( 'variation' ) ) { + $this->product = dokan()->product->get( $this->product->get_parent_id() ); + } + } + + + /** + * Returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get(): Setting { + $percentage = ''; + $type = ''; + $flat = ''; + + if ( is_a( $this->product, WC_Product::class ) && $this->product->get_id() ) { + $percentage = $this->product->get_meta( '_per_product_admin_commission', true ); + $type = $this->product->get_meta( '_per_product_admin_commission_type', true ); + $flat = $this->product->get_meta( '_per_product_admin_additional_fee', true ); + } + + $settings = new Setting(); + $settings->set_type( $type ) + ->set_flat( $flat ) + ->set_percentage( $percentage ); + + return $settings; + } + + /** + * Saves and returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @param array $setting { + * + * @type string $percentage + * @type string $type + * @type string $flat + * } + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save( array $setting ): Setting { + $commission_percentage = isset( $setting['percentage'] ) ? $setting['percentage'] : ''; + $commission_type = isset( $setting['type'] ) ? $setting['type'] : ''; + $additional_flat = isset( $setting['flat'] ) ? $setting['flat'] : ''; + + if ( is_a( $this->product, WC_Product::class ) && $this->product->get_id() ) { + $this->product->update_meta_data( '_per_product_admin_commission', $commission_percentage ); + $this->product->update_meta_data( '_per_product_admin_commission_type', $commission_type ); + $this->product->update_meta_data( '_per_product_admin_additional_fee', $additional_flat ); + + $this->product->save_meta_data(); + $this->product->save(); + } + + $commission = new Setting(); + $commission->set_type( $commission_type ) + ->set_flat( $additional_flat ) + ->set_percentage( $commission_percentage ); + + return $commission; + } +} diff --git a/includes/Commission/Settings/Vendor.php b/includes/Commission/Settings/Vendor.php new file mode 100644 index 0000000000..54106d7a65 --- /dev/null +++ b/includes/Commission/Settings/Vendor.php @@ -0,0 +1,97 @@ +vendor = dokan()->vendor->get( $vendor_id ); + } + + + /** + * Returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get(): Setting { + $percentage = ''; + $type = ''; + $flat = ''; + $category_commissions = []; + + if ( 0 !== $this->vendor->get_id() ) { + $percentage = $this->vendor->get_meta( 'dokan_admin_percentage', true ); + $type = $this->vendor->get_meta( 'dokan_admin_percentage_type', true ); + $flat = $this->vendor->get_meta( 'dokan_admin_additional_fee', true ); + $category_commissions = $this->vendor->get_meta( 'admin_category_commission', true ); + + $category_commissions = ! is_array( $category_commissions ) ? [] : $category_commissions; + } + + $settings = new Setting(); + $settings->set_type( $type ) + ->set_flat( $flat ) + ->set_percentage( $percentage ) + ->set_category_commissions( $category_commissions ); + + return $settings; + } + + /** + * Saves and returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @param array $setting { + * + * @type string $percentage + * @type string $type + * @type string $flat + * @type array $category_commissions + * } + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save( array $setting ): Setting { + if ( ! $this->vendor->get_id() ) { + return $this->get(); + } + + $percentage = isset( $setting['percentage'] ) ? $setting['percentage'] : ''; + $type = isset( $setting['type'] ) ? $setting['type'] : ''; + $flat = isset( $setting['flat'] ) ? $setting['flat'] : ''; + $category_commissions = isset( $setting['category_commissions'] ) ? $setting['category_commissions'] : []; + + $this->vendor->update_meta( 'dokan_admin_percentage', $percentage ); + $this->vendor->update_meta( 'dokan_admin_percentage_type', $type ); + $this->vendor->update_meta( 'dokan_admin_additional_fee', $flat ); + $this->vendor->update_meta( 'admin_category_commission', $category_commissions ); + + return $this->get(); + } + + public function delete() { + if ( ! $this->vendor->get_id() ) { + return $this->get(); + } + + delete_user_meta( $this->vendor->get_id(), 'dokan_admin_percentage' ); + delete_user_meta( $this->vendor->get_id(), 'dokan_admin_percentage_type' ); + delete_user_meta( $this->vendor->get_id(), 'dokan_admin_additional_fee' ); + delete_user_meta( $this->vendor->get_id(), 'admin_category_commission' ); + } +} diff --git a/includes/Commission/Strategies/AbstractStrategy.php b/includes/Commission/Strategies/AbstractStrategy.php new file mode 100644 index 0000000000..03762f13b8 --- /dev/null +++ b/includes/Commission/Strategies/AbstractStrategy.php @@ -0,0 +1,41 @@ +get_settings(); + + return FormulaFactory::get_formula( $settings ); + } +} diff --git a/includes/Commission/Strategies/DefaultStrategy.php b/includes/Commission/Strategies/DefaultStrategy.php new file mode 100644 index 0000000000..d1c9bd26c6 --- /dev/null +++ b/includes/Commission/Strategies/DefaultStrategy.php @@ -0,0 +1,50 @@ +get(); + + $setting->set_type( DefaultSetting::TYPE ) + ->set_flat( 0 ) + ->set_percentage( 0 ) + ->set_category_commissions( [] ); + + return $setting; + } +} diff --git a/includes/Commission/Strategies/GlobalStrategy.php b/includes/Commission/Strategies/GlobalStrategy.php new file mode 100644 index 0000000000..77df8d366f --- /dev/null +++ b/includes/Commission/Strategies/GlobalStrategy.php @@ -0,0 +1,71 @@ +category_id = $category_id; + } + + /** + * Returns category id. + * + * @since DOKAN_SINCE + * + * @return mixed + */ + public function get_category_id() { + return $this->category_id; + } + + /** + * Returns global strategy source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns global commission settings. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_settings(): Setting { + $setting = Builder::build( Builder::TYPE_GLOBAL, $this->get_category_id() ); + + return $setting->get(); + } +} diff --git a/includes/Commission/Strategies/OrderItem.php b/includes/Commission/Strategies/OrderItem.php new file mode 100644 index 0000000000..68a7955b55 --- /dev/null +++ b/includes/Commission/Strategies/OrderItem.php @@ -0,0 +1,125 @@ +order_item_id = $order_item_id; + $this->total_amount = $total_amount; + $this->total_quantity = $total_quantity; + } + + /** + * Returns order item strategy source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns order item commission settings. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_settings(): Setting { + $settings = Builder::build( + Builder::TYPE_ORDER_ITEM, + [ + 'id' => $this->order_item_id, + 'price' => $this->total_amount, + ] + ); + + return $settings->get(); + } + + /** + * Save order item commission meta data. + * + * @since DOKAN_SINCE + * + * @param string $type + * @param int|float $percentage + * @param int|float $flat + * @param array $meta_data + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save_line_item_commission_to_meta( $type, $percentage, $flat, $meta_data ) { + $settings = Builder::build( + Builder::TYPE_ORDER_ITEM, + [ + 'id' => $this->order_item_id, + 'price' => $this->total_amount, + ] + ); + + return $settings->save( + [ + 'type' => $type, + 'percentage' => $percentage, + 'flat' => $flat, + 'meta_data' => $meta_data , + ] + ); + } +} diff --git a/includes/Commission/Strategies/Product.php b/includes/Commission/Strategies/Product.php new file mode 100644 index 0000000000..73c287d4fb --- /dev/null +++ b/includes/Commission/Strategies/Product.php @@ -0,0 +1,60 @@ +product_id = $product_id; + } + + /** + * Returns product strategy source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns product commission settings. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_settings(): Setting { + $settings = Builder::build( Builder::TYPE_PRODUCT, $this->product_id ); + + return $settings->get(); + } +} diff --git a/includes/Commission/Strategies/Vendor.php b/includes/Commission/Strategies/Vendor.php new file mode 100644 index 0000000000..eff53fbac9 --- /dev/null +++ b/includes/Commission/Strategies/Vendor.php @@ -0,0 +1,86 @@ +vendor_id = $vendor_id; + $this->category_id = $category_id; + } + + /** + * Returns category id. + * + * @since DOKAN_SINCE + * + * @return int + */ + public function get_category_id() { + return $this->category_id; + } + + /** + * Returns vendor commission source. + * + * @since DOKAN_SINCE + * + * @return string + */ + public function get_source(): string { + return self::SOURCE; + } + + /** + * Returns vendor commission settings. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_settings(): Setting { + $settings = Builder::build( Builder::TYPE_VENDOR, $this->vendor_id ); + $settings = $settings->get(); + $settings->set_category_id( $this->get_category_id() ); + + return $settings; + } +} diff --git a/includes/DependencyManagement/Providers/ServiceProvider.php b/includes/DependencyManagement/Providers/ServiceProvider.php index 19c5e1696d..9ae5b8e70c 100644 --- a/includes/DependencyManagement/Providers/ServiceProvider.php +++ b/includes/DependencyManagement/Providers/ServiceProvider.php @@ -36,6 +36,7 @@ class ServiceProvider extends BootableServiceProvider { 'withdraw' => \WeDevs\Dokan\Withdraw\Manager::class, 'dashboard' => \WeDevs\Dokan\Dashboard\Manager::class, 'commission' => \WeDevs\Dokan\Commission::class, + 'fees' => \WeDevs\Dokan\Fees::class, 'customizer' => \WeDevs\Dokan\Customizer::class, 'upgrades' => \WeDevs\Dokan\Upgrade\Manager::class, 'product_sections' => \WeDevs\Dokan\ProductSections\Manager::class, diff --git a/includes/Fees.php b/includes/Fees.php new file mode 100644 index 0000000000..4f386fe5e4 --- /dev/null +++ b/includes/Fees.php @@ -0,0 +1,268 @@ +commission in version in DOKAN_SINCE + * + * @since DOKAN_SINCE + * + * @return void + */ + public function __construct() { + add_filter( 'woocommerce_order_item_get_formatted_meta_data', [ $this, 'hide_extra_data' ] ); + add_action( 'woocommerce_order_status_changed', [ $this, 'calculate_gateway_fee' ], 100 ); + add_action( 'woocommerce_thankyou_ppec_paypal', [ $this, 'calculate_gateway_fee' ] ); + add_action( 'woocommerce_paypal_payments_order_captured', [ $this, 'calculate_gateway_fee' ], 99 ); + } + + /** + * Hide extra meta data + * + * @since 2.9.21 + * + * @param array + * + * @return array + */ + public function hide_extra_data( $formatted_meta ) { + $meta_to_hide = [ '_dokan_commission_rate', '_dokan_commission_type', '_dokan_additional_fee' ]; + + foreach ( $formatted_meta as $key => $meta ) { + if ( in_array( $meta->key, $meta_to_hide, true ) ) { + unset( $formatted_meta[ $key ] ); + } + } + + return $formatted_meta; + } + + /** + * Calculate gateway fee + * Moved from dokan()->commission in version in DOKAN_SINCE + * + * @since 2.9.21 + * + * @param int $order_id + * + * @return void + */ + public function calculate_gateway_fee( $order_id ) { + global $wpdb; + $order = wc_get_order( $order_id ); + $processing_fee = $this->get_processing_fee( $order ); + + if ( ! $processing_fee ) { + return; + } + + foreach ( dokan()->commission->get_all_order_to_be_processed( $order ) as $tmp_order ) { + $gateway_fee_added = $tmp_order->get_meta( 'dokan_gateway_fee' ); + $vendor_earning = dokan()->commission->get_earning_from_order_table( $tmp_order->get_id() ); + + if ( is_null( $vendor_earning ) || $gateway_fee_added ) { + continue; + } + + $gateway_fee = wc_format_decimal( ( $processing_fee / $order->get_total() ) * $tmp_order->get_total() ); + + // Ensure sub-orders also get the correct payment gateway fee (if any) + $gateway_fee = apply_filters( 'dokan_get_processing_gateway_fee', $gateway_fee, $tmp_order, $order ); + $net_amount = $vendor_earning - $gateway_fee; + $net_amount = apply_filters( 'dokan_orders_vendor_net_amount', $net_amount, $vendor_earning, $gateway_fee, $tmp_order, $order ); + + $wpdb->update( + $wpdb->dokan_orders, + [ 'net_amount' => (float) $net_amount ], + [ 'order_id' => $tmp_order->get_id() ], + [ '%f' ], + [ '%d' ] + ); + + $wpdb->update( + $wpdb->dokan_vendor_balance, + [ 'debit' => (float) $net_amount ], + [ + 'trn_id' => $tmp_order->get_id(), + 'trn_type' => 'dokan_orders', + ], + [ '%f' ], + [ '%d', '%s' ] + ); + + $tmp_order->update_meta_data( 'dokan_gateway_fee', $gateway_fee ); + $tmp_order->save(); + + if ( apply_filters( 'dokan_commission_log_gateway_fee_to_order_note', true, $tmp_order ) ) { + // translators: %s: Geteway fee + $tmp_order->add_order_note( sprintf( __( 'Payment gateway processing fee %s', 'dokan-lite' ), wc_format_decimal( $gateway_fee, 2 ) ) ); + } + //remove cache for seller earning + $cache_key = "get_earning_from_order_table_{$tmp_order->get_id()}_seller"; + Cache::delete( $cache_key ); + + // remove cache for seller earning + $cache_key = "get_earning_from_order_table_{$tmp_order->get_id()}_admin"; + Cache::delete( $cache_key ); + } + } + + /** + * Get processing fee + * + * @since DOKAN_LITE_SINCE + * + * @param WC_Order $order + * + * @return float + */ + public function get_processing_fee( $order ) { + $processing_fee = 0; + $payment_method = $order->get_payment_method(); + + if ( 'paypal' === $payment_method ) { + $processing_fee = $order->get_meta( 'PayPal Transaction Fee' ); + } elseif ( 'ppec_paypal' === $payment_method && defined( 'PPEC_FEE_META_NAME_NEW' ) ) { + $processing_fee = $order->get_meta( PPEC_FEE_META_NAME_NEW ); + } elseif ( 'ppcp-gateway' === $payment_method && class_exists( PayPalGateway::class ) ) { + $breakdown = $order->get_meta( PayPalGateway::FEES_META_KEY ); + if ( is_array( $breakdown ) && isset( $breakdown['paypal_fee'] ) && is_array( $breakdown['paypal_fee'] ) ) { + $processing_fee = $breakdown['paypal_fee']['value']; + } + } + + return apply_filters( 'dokan_get_processing_fee', $processing_fee, $order ); + } + + /** + * Get shipping fee recipient + * Move from commission.php in version DOKAN_SINCE + * + * @since 2.9.21 + * @since 3.4.1 introduced the shipping fee recipient hook + * + * @param WC_Order|int $order + * + * @return string + */ + public function get_shipping_fee_recipient( $order ) { + if ( is_numeric( $order ) ) { + $order = wc_get_order( $order ); + } + + if ( ! $order ) { + return new WP_Error( 'invalid-order-object', __( 'Please provide a valid order object.', 'dokan-lite' ) ); + } + + $saved_shipping_recipient = $order->get_meta( 'shipping_fee_recipient', true ); + + if ( $saved_shipping_recipient ) { + $shipping_recipient = $saved_shipping_recipient; + } else { + $shipping_recipient = apply_filters( 'dokan_shipping_fee_recipient', dokan_get_option( 'shipping_fee_recipient', 'dokan_selling', 'seller' ), $order->get_id() ); + $order->update_meta_data( 'shipping_fee_recipient', $shipping_recipient ); + $order->save(); + } + + return $shipping_recipient; + } + + /** + * Get tax fee recipient + * Move from commission.php in version DOKAN_SINCE + * + * @since 2.9.21 + * @since 3.4.1 introduced the tax fee recipient hook + * + * @param WC_Order|int $order + * + * @return string|WP_Error + */ + public function get_tax_fee_recipient( $order ) { + if ( is_numeric( $order ) ) { + $order = wc_get_order( $order ); + } + + if ( ! $order ) { + return new WP_Error( 'invalid-order-object', __( 'Please provide a valid order object.', 'dokan-lite' ) ); + } + + $saved_tax_recipient = $order->get_meta( 'tax_fee_recipient', true ); + + if ( $saved_tax_recipient ) { + $tax_recipient = $saved_tax_recipient; + } else { + $tax_recipient = apply_filters( 'dokan_tax_fee_recipient', dokan_get_option( 'tax_fee_recipient', 'dokan_selling', 'seller' ), $order->get_id() ); + $order->update_meta_data( 'tax_fee_recipient', $tax_recipient ); + $order->save(); + } + + return $tax_recipient; + } + + /** + * Get shipping tax fee recipient. + * Move from commission.php in version DOKAN_SINCE + * + * @since 3.7.19 + * + * @param WC_Order $order Order. + * + * @return string + */ + public function get_shipping_tax_fee_recipient( $order ): string { + // get saved tax recipient + $saved_shipping_tax_recipient = $order->get_meta( 'shipping_tax_fee_recipient', true ); + if ( ! empty( $saved_shipping_tax_recipient ) ) { + return $saved_shipping_tax_recipient; + } + + $default_tax_fee_recipient = $this->get_tax_fee_recipient( $order->get_id() ); // this is needed for backward compatibility + $shipping_tax_recipient = dokan_get_option( 'shipping_tax_fee_recipient', 'dokan_selling', $default_tax_fee_recipient ); + $shipping_tax_recipient = apply_filters( 'dokan_shipping_tax_fee_recipient', $shipping_tax_recipient, $order->get_id() ); + + $order->update_meta_data( 'shipping_tax_fee_recipient', $shipping_tax_recipient, true ); + $order->save(); + + return $shipping_tax_recipient; + } + + /** + * Get total shipping tax refunded for the order. + * Move from commission.php in version DOKAN_SINCE + * + * @since 3.7.19 + * + * @param WC_Order $order Order. + * + * @return float + */ + public function get_total_shipping_tax_refunded( WC_Order $order ): float { + $tax_refunded = 0.0; + + foreach ( $order->get_items( 'shipping' ) as $item_id => $item ) { + /** + * @var \WC_Order_Item_Shipping $item Shipping item. + */ + foreach ( $item->get_taxes()['total'] as $tax_id => $tax_amount ) { + $tax_refunded += $order->get_tax_refunded_for_item( $item->get_id(), $tax_id, 'shipping' ); + } + } + + return $tax_refunded; + } +} diff --git a/includes/Order/Admin/Hooks.php b/includes/Order/Admin/Hooks.php index 1e8631127c..6608346fb1 100644 --- a/includes/Order/Admin/Hooks.php +++ b/includes/Order/Admin/Hooks.php @@ -55,6 +55,9 @@ public function __construct() { add_filter( 'woocommerce_order_item_display_meta_value', [ $this, 'change_order_item_display_meta_value' ], 10, 2 ); add_filter( 'woocommerce_reports_get_order_report_query', [ $this, 'admin_order_reports_remove_parents' ] ); add_filter( 'post_class', [ $this, 'admin_shop_order_row_classes' ], 10, 3 ); + + // Add commission meta-box in order details page. + add_action( 'add_meta_boxes', [ $this, 'add_commission_metabox_and_related_orders_in_order_details_page' ], 10, 2 ); } /** @@ -89,9 +92,10 @@ public function admin_shop_order_edit_columns( $existing_columns ) { } $column_to_insert = [ - 'seller' => __( 'Vendor', 'dokan-lite' ), - 'wc_actions' => __( 'Actions', 'dokan-lite' ), - 'suborder' => __( 'Sub Order', 'dokan-lite' ), + 'admin_commission' => __( 'Commission', 'dokan-lite' ), + 'seller' => __( 'Vendor', 'dokan-lite' ), + 'wc_actions' => __( 'Actions', 'dokan-lite' ), + 'suborder' => __( 'Sub Order', 'dokan-lite' ), ]; $columns = dokan_array_insert_after( $existing_columns, $column_to_insert ); @@ -120,7 +124,7 @@ public function shop_order_custom_columns( $col, $post_id ) { return; } - if ( ! in_array( $col, [ 'order_number', 'suborder', 'seller' ], true ) ) { + if ( ! in_array( $col, [ 'order_number', 'suborder', 'seller', 'admin_commission' ], true ) ) { return; } @@ -155,6 +159,21 @@ public function shop_order_custom_columns( $col, $post_id ) { } break; + + case 'admin_commission': + if ( '1' === $order->get_meta( 'has_sub_order', true ) ) { + $output = '--'; + } else { + $commission = dokan()->commission->get_earning_by_order( $order->get_id(), 'admin' ); + /** + * In case of refund, we are not excluding gateway fee; in case of stripe full/partial refund net amount can be negative + */ + if ( $commission < 0 ) { + $commission = 0; + } + $output = wc_price( $commission ); + } + break; } if ( ! empty( $output ) ) { @@ -513,4 +532,127 @@ public function admin_shop_order_toggle_sub_orders( $typenow ) { echo ''; } } + + /** + * Add dokan commission meta-box in woocommerce order details page + * and add suborders or related sibling orders in meta-box. + * + * @since DOKAN_SINCE + * + * @return void + */ + public function add_commission_metabox_and_related_orders_in_order_details_page( $post_type, $post ) { + $screen = OrderUtil::get_order_admin_screen(); + + if ( $screen !== $post_type ) { + return; + } + + $order = dokan()->order->get( OrderUtil::get_post_or_order_id( $post ) ); + $has_sub_order = '1' === $order->get_meta( 'has_sub_order', true ); + + // Check if the screen is order details page and if it is a child order. + if ( ! $has_sub_order ) { + add_meta_box( + 'dokan_commission_box', + __( 'Commissions', 'dokan-lite' ), + [ $this, 'commission_meta_box' ], + $screen, + 'normal', + 'core' + ); + } + + // If the order has is a parent order or a child order, avoid those order that has no parent order or child order. + if ( $has_sub_order || ! empty( $order->get_parent_id() ) ) { + $title = $has_sub_order ? __( 'Sub orders', 'dokan-lite' ) : __( 'Related orders', 'dokan-lite' ); + + add_meta_box( + 'dokan_sub_or_related_orders', + $title, + [ $this, 'sub_or_related_orders_meta_box' ], + $screen, + 'normal', + 'core' + ); + } + } + + /** + * Dokan order commission meta-box body. + * + * @since DOKAN_SINCE + * + * @param WP_Post|WC_Order $post_or_order + * + * @return void + */ + public function commission_meta_box( $post_or_order ) { + global $wpdb; + $order = dokan()->order->get( OrderUtil::get_post_or_order_id( $post_or_order ) ); + + $data = $wpdb->get_row( + $wpdb->prepare( "SELECT order_total,net_amount FROM {$wpdb->prefix}dokan_orders WHERE order_id = %d LIMIT 1", $order->get_id() ) + ); + + $order_total = $data && property_exists( $data, 'order_total' ) ? $data->order_total : 0; + $net_amount = $data && property_exists( $data, 'net_amount' ) ? $data->net_amount : 0; + + $total_commission = (float) $order_total - (float) $net_amount; + $all_commission_types = array_merge( dokan_commission_types(), dokan()->commission->get_legacy_commission_types() ); + + dokan_get_template_part( + 'orders/commission-meta-box-html', '', [ + 'order' => $order, + 'data' => $data, + 'total_commission' => $total_commission, + 'all_commission_types' => $all_commission_types, + ] + ); + } + + /** + * Content of suborder or related order meta-box. + * + * @param $post_or_order + * + * @return void + */ + public function sub_or_related_orders_meta_box( $post_or_order ) { + $order = dokan()->order->get( OrderUtil::get_post_or_order_id( $post_or_order ) ); + $parent_order = new WC_Order(); + $has_sub_order = '1' === $order->get_meta( 'has_sub_order', true ); + + if ( $has_sub_order ) { + $orders_to_render = dokan()->order->get_child_orders( $order->get_id() ); + } else { + $orders_to_render = dokan()->order->all( + [ + 'parent' => $order->get_parent_id(), + 'limit' => -1, + 'type' => 'shop_order', + ] + ); + + $parent_order = dokan()->order->get( $order->get_parent_id() ); + + $orders_to_render = array_filter( + $orders_to_render, + function ( $item ) use ( $order ) { + return $item->get_id() !== $order->get_id(); + } + ); + + array_unshift( $orders_to_render, $parent_order ); + } + + dokan_get_template_part( + 'orders/sub-order-related-order-meta-box-html', '', array( + 'order' => $order, + 'parent_order' => $parent_order, + 'has_sub_order' => $has_sub_order, + 'orders_to_render' => $orders_to_render, + ) + ); + } } diff --git a/includes/Product/Hooks.php b/includes/Product/Hooks.php index 6543cb504a..961e19556d 100644 --- a/includes/Product/Hooks.php +++ b/includes/Product/Hooks.php @@ -40,6 +40,11 @@ public function __construct() { // Init Product Cache Class new VendorStoreInfo(); new ProductCache(); + + // Product commission + add_action( 'woocommerce_product_options_advanced', array( $this, 'add_per_product_commission_options' ), 15 ); + add_action( 'woocommerce_process_product_meta_simple', array( $this, 'save_per_product_commission_options' ), 15 ); + add_action( 'woocommerce_process_product_meta_variable', array( $this, 'save_per_product_commission_options' ), 15 ); } /** @@ -453,4 +458,96 @@ public function product_review_notification_recipients( $emails, $comment_id ) { return $filtered_emails; } + + /** + * Add per product commission options + * Moved from dokan pro in version DOKAN_SINCE + * + * @since 2.4.12 + * + * @return void + */ + public function add_per_product_commission_options() { + if ( ! current_user_can( 'manage_woocommerce' ) ) { + return; + } + + $product = wc_get_product( get_the_ID() ); + $admin_commission = $product->get_meta( '_per_product_admin_commission' ); + $additional_fee = $product->get_meta( '_per_product_admin_additional_fee' ); + ?> + +
+

+ + + + + + + + + + + +

+
+ + + get( $product_id ); + if ( ! $product ) { + return 0; + } + + $parent_id = $product->get_parent_id(); + + return $parent_id ? $parent_id : $product_id; + } + + /** + * Returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_commission_settings( $product_id = 0 ) { + $settings = new Product( $product_id ); + + return $settings->get(); + } + + /** + * Saves and returns product commission settings data. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save_commission_settings( $product_id, $commission ) { + $data['percentage'] = isset( $commission['percentage'] ) ? $commission['percentage'] : ''; + $data['type'] = isset( $commission['type'] ) ? $commission['type'] : ''; + $data['flat'] = isset( $commission['flat'] ) ? $commission['flat'] : ''; + + $setting = new Product( $product_id ); + return $setting->save( $data ); + } } diff --git a/includes/ProductCategory/Helper.php b/includes/ProductCategory/Helper.php index b8bdfd671e..c582787ff6 100644 --- a/includes/ProductCategory/Helper.php +++ b/includes/ProductCategory/Helper.php @@ -99,13 +99,17 @@ private static function get_formatted_chosen_cat( $all_children, $all_ancestors * * @since 3.6.4 * - * @param object $terms + * @param array $terms * * @return array */ public static function generate_chosen_categories( $terms ) { $all_parents = []; + if ( ! is_array( $terms ) ) { + $terms = []; + } + // If any category selection option is turned we don't need to generate chosen categories, all terms are also chosen category. if ( self::is_any_category_selection_enabled() ) { return $terms; diff --git a/includes/REST/AdminMiscController.php b/includes/REST/AdminMiscController.php index 6716d8c3ae..97c959d910 100644 --- a/includes/REST/AdminMiscController.php +++ b/includes/REST/AdminMiscController.php @@ -36,6 +36,30 @@ public function register_routes() { ), ) ); + + register_rest_route( + $this->namespace, '/option', [ + [ + 'methods' => WP_REST_Server::READABLE, + 'callback' => [ $this, 'get_option' ], + 'args' => [ + 'section' => [ + 'type' => 'string', + 'description' => __( 'Dokan setting section', 'dokan-lite' ), + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field', + ], + 'option' => [ + 'type' => 'string', + 'description' => __( 'Dokan setting section key', 'dokan-lite' ), + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field', + ], + ], + 'permission_callback' => [ $this, 'check_permission' ], + ], + ] + ); } /** @@ -51,4 +75,20 @@ public function get_help() { return rest_ensure_response( $help ); } + /** + * Get dokan option. + * + * @since DOKAN_SINCE + * + * @param \WP_REST_Request $request + * + * @return \WP_REST_Response|\WP_Error + */ + public function get_option( $request ) { + $section = $request->get_param( 'section' ); + $option = $request->get_param( 'option' ); + $default = ''; + + return rest_ensure_response( dokan_get_option( $option, $section, $default ) ); + } } diff --git a/includes/REST/CommissionControllerV1.php b/includes/REST/CommissionControllerV1.php new file mode 100644 index 0000000000..f9c94f8309 --- /dev/null +++ b/includes/REST/CommissionControllerV1.php @@ -0,0 +1,143 @@ +namespace, '/' . $this->base, [ + [ + 'methods' => WP_REST_Server::READABLE, + 'callback' => [ $this, 'get_commission' ], + 'args' => [ + 'product_id' => [ + 'description' => __( 'Products price', 'dokan-lite' ), + 'type' => 'integer', + 'default' => 0, + 'required' => true, + 'sanitize_callback' => 'absint', + ], + 'amount' => [ + 'description' => __( 'The amount on that the commission will be calculated.', 'dokan-lite' ), + 'type' => 'number', + 'default' => 0, + 'required' => true, + 'sanitize_callback' => 'sanitize_text_field', + ], + 'vendor_id' => [ + 'description' => __( 'Vendor id', 'dokan-lite' ), + 'type' => 'integer', + 'default' => 0, + 'required' => true, + 'sanitize_callback' => 'absint', + ], + 'category_ids' => [ + 'description' => __( 'Category ids', 'dokan-lite' ), + 'type' => 'array', + 'sanitize_callback' => 'wc_clean', + 'items' => array( + 'type' => 'integer', + ), + 'default' => [], + 'required' => true, + ], + 'context' => [ + 'required' => false, + 'description' => __( 'In which context the commission will be calculated', 'dokan-lite' ), + 'type' => 'string', + 'enum' => [ 'admin', 'seller' ], + 'context' => [ 'view', 'edit' ], + 'default' => 'seller', + ], + ], + 'permission_callback' => [ $this, 'get_permissions_check' ], + ], + ] + ); + } + + /** + * Checking if have any permission. + * + * @since DOKAN_SINCE + * + * @return boolean + */ + public function get_permissions_check() { + // phpcs:ignore WordPress.WP.Capabilities.Unknown + return current_user_can( 'dokandar' ) || current_user_can( 'manage_options' ); + } + + /** + * Returns commission or earning based on context. + * + * @param WP_REST_Request $request + * + * @return WP_Error|WP_HTTP_Response|WP_REST_Response + */ + public function get_commission( $request ) { + $product_id = $request->get_param( 'product_id' ); + $amount = $request->get_param( 'amount' ); + $vendor_id = $request->get_param( 'vendor_id' ); + $category_ids = $request->get_param( 'category_ids' ); + $context = $request->get_param( 'context' ); + + $chosen_cats = Helper::generate_chosen_categories( $category_ids ); + $category_id = reset( $chosen_cats ); + + if ( ! $category_id ) { + $category_id = 0; + } + + if ( ! $vendor_id ) { + $vendor_id = dokan_get_vendor_by_product( $product_id, true ); + $vendor_id = $vendor_id ? $vendor_id : 0; + } + + if ( ! is_numeric( $amount ) ) { + $amount = 0; + } + + $commission_or_earning = dokan()->commission->get_commission( + [ + 'total_amount' => $amount, + 'total_quantity' => 1, + 'product_id' => $product_id, + 'vendor_id' => $vendor_id, + 'category_id' => $category_id, + ] + ); + + $data = 'seller' === $context ? $commission_or_earning->get_vendor_earning() : $commission_or_earning->get_admin_commission(); + + return rest_ensure_response( wc_format_decimal( $data, wc_get_price_decimals() + 2 ) ); + } +} diff --git a/includes/REST/Manager.php b/includes/REST/Manager.php index ce0d1f936b..10d0a5970d 100644 --- a/includes/REST/Manager.php +++ b/includes/REST/Manager.php @@ -27,9 +27,6 @@ public function __construct() { add_filter( 'woocommerce_rest_prepare_product_object', array( $this, 'prepeare_product_response' ), 10, 3 ); add_filter( 'dokan_vendor_to_array', array( $this, 'filter_store_open_close_option' ) ); - // populate admin commission data for admin - add_filter( 'dokan_rest_store_additional_fields', array( $this, 'populate_admin_commission' ), 10, 2 ); - // Send email to admin on adding a new product add_action( 'dokan_rest_insert_product_object', array( $this, 'on_dokan_rest_insert_product' ), 10, 3 ); add_filter( 'dokan_vendor_to_array', [ $this, 'filter_payment_response' ] ); @@ -130,37 +127,6 @@ public function filter_store_open_close_option( $data ) { return $data; } - /** - * Populate admin commission - * - * @param array $data - * @param array $store - * - * @since 2.9.13 - * - * @return array - */ - public function populate_admin_commission( $data, $store ) { - if ( ! current_user_can( 'manage_woocommerce' ) ) { - return $data; - } - - $store_id = $store->get_id(); - - if ( ! $store_id ) { - return $data; - } - - $commission = get_user_meta( $store_id, 'dokan_admin_percentage', true ); - $additional_fee = get_user_meta( $store_id, 'dokan_admin_additional_fee', true ); - $commission_type = get_user_meta( $store_id, 'dokan_admin_percentage_type', true ); - $data['admin_commission'] = $commission; - $data['admin_additional_fee'] = $additional_fee; - $data['admin_commission_type'] = $commission_type; - - return $data; - } - /** * Send email to admin on adding a new product * @@ -234,6 +200,7 @@ private function get_rest_api_class_map() { DOKAN_DIR . '/includes/REST/StoreSettingControllerV2.php' => '\WeDevs\Dokan\REST\StoreSettingControllerV2', DOKAN_DIR . '/includes/REST/VendorDashboardController.php' => '\WeDevs\Dokan\REST\VendorDashboardController', DOKAN_DIR . '/includes/REST/ProductBlockController.php' => '\WeDevs\Dokan\REST\ProductBlockController', + DOKAN_DIR . '/includes/REST/CommissionControllerV1.php' => '\WeDevs\Dokan\REST\CommissionControllerV1', ) ); } diff --git a/includes/REST/ProductControllerV2.php b/includes/REST/ProductControllerV2.php index 2015555b87..60d21506a9 100644 --- a/includes/REST/ProductControllerV2.php +++ b/includes/REST/ProductControllerV2.php @@ -2,6 +2,8 @@ namespace WeDevs\Dokan\REST; +use WP_Error; +use WP_REST_Response; use WP_REST_Server; use WP_REST_Request; use WeDevs\Dokan\ProductCategory\Helper; diff --git a/includes/REST/StoreController.php b/includes/REST/StoreController.php index d0e491e99f..f6d71edafc 100644 --- a/includes/REST/StoreController.php +++ b/includes/REST/StoreController.php @@ -623,14 +623,21 @@ public function get_total_review_count( $id, $post_type, $status ) { /** * Prepare a single user output for response * - * @param $store + * @param Vendor $store * @param WP_REST_Request $request Request object. * @param array $additional_fields (optional) * * @return WP_REST_Response $response Response data. */ public function prepare_item_for_response( $store, $request, $additional_fields = [] ) { - $data = $store->to_array(); + $data = $store->to_array(); + + $commission_settings = $store->get_commission_settings(); + $data['admin_category_commission'] = $commission_settings->get_category_commissions(); + $data['admin_commission'] = $commission_settings->get_percentage(); + $data['admin_additional_fee'] = $commission_settings->get_flat(); + $data['admin_commission_type'] = $commission_settings->get_type(); + $data = array_merge( $data, apply_filters( 'dokan_rest_store_additional_fields', $additional_fields, $store, $request ) ); $response = rest_ensure_response( $data ); $response->add_links( $this->prepare_links( $data, $request ) ); @@ -935,7 +942,22 @@ public function get_store_category( $request ) { } $category_data = $store->get_store_categories( $best_selling ); - $response = rest_ensure_response( $category_data ); + $commission_settings = $store->get_commission_settings(); + $category_commissions = $commission_settings->get_category_commissions(); + + foreach ( $category_data as $term ) { + $term->admin_commission_type = $commission_settings->get_type(); + + if ( isset( $category_commissions['items'][ $term->term_id ] ) ) { + $term->commission = $category_commissions['items'][ $term->term_id ]; + } elseif ( $category_commissions['all'] ) { + $term->commission = $category_commissions['all']; + } else { + $term->commission = []; + } + } + + $response = rest_ensure_response( $category_data ); return $response; } diff --git a/includes/Upgrade/Upgrades.php b/includes/Upgrade/Upgrades.php index a81110997f..8f40c6b2c7 100644 --- a/includes/Upgrade/Upgrades.php +++ b/includes/Upgrade/Upgrades.php @@ -44,6 +44,7 @@ class Upgrades { '3.7.10' => Upgrades\V_3_7_10::class, '3.7.19' => Upgrades\V_3_7_19::class, '3.13.0' => Upgrades\V_3_13_0::class, + '4.0.0' => Upgrades\V_4_0_0::class, ]; /** diff --git a/includes/Upgrade/Upgrades/BackgroundProcesses/V_4_0_0_UpdateCommissions.php b/includes/Upgrade/Upgrades/BackgroundProcesses/V_4_0_0_UpdateCommissions.php new file mode 100644 index 0000000000..618e62ea01 --- /dev/null +++ b/includes/Upgrade/Upgrades/BackgroundProcesses/V_4_0_0_UpdateCommissions.php @@ -0,0 +1,130 @@ +update_global_settings( $item['data'] ); + } + + if ( isset( $item['task'] ) && 'vendors-commission' === $item['task'] ) { + return $this->update_vendors_settings( $item['data'] ); + } + + if ( isset( $item['task'] ) && 'products-commission' === $item['task'] ) { + return $this->update_products_settings( $item['data'] ); + } + + return false; + } + + /** + * Update global category commissions. + * + * @since DOKAN_SINCE + * + * @param WP_Term[] $terms + * + * @return true + */ + private function update_global_settings( $terms ) { + $dokan_selling = get_option( 'dokan_selling', [] ); + $category_commission = dokan_get_option( 'commission_category_based_values', 'dokan_selling', [] ); + + foreach ( $terms as $term ) { + $commission_type = get_term_meta( $term->term_id, 'per_category_admin_commission_type', true ); + $admin_additional_fee = get_term_meta( $term->term_id, 'per_category_admin_additional_fee', true ); + $commission = get_term_meta( $term->term_id, 'per_category_admin_commission', true ); + + if ( ! empty( $commission_type ) ) { + $category_commission['items'][ $term->term_id ] = [ + 'flat' => $admin_additional_fee, + 'percentage' => $commission, + ]; + } + } + + $dokan_selling['commission_category_based_values'] = $category_commission; + update_option( 'dokan_selling', $dokan_selling ); + + return true; + } + + /** + * Update vendor commission settings. + * + * @since DOKAN_SINCE + * + * @param \WeDevs\Dokan\Vendor\Vendor[] $vendors + * + * @return bool + */ + private function update_vendors_settings( $vendors ) { + foreach ( $vendors as $vendor ) { + $commission = $vendor->get_commission_settings(); + $commission->set_type( Fixed::SOURCE ); + + $vendor->save_commission_settings( + [ + 'percentage' => $commission->get_percentage(), + 'type' => $commission->get_type(), + 'flat' => $commission->get_flat(), + 'category_commissions' => $commission->get_category_commissions(), + ] + ); + } + + return true; + } + + /** + * Update product commission settings. + * + * @since DOKAN_SINCE + * + * @param \WP_Post[] $posts + * + * @return bool + */ + private function update_products_settings( $posts ) { + foreach ( $posts as $post ) { + $commission = dokan()->product->get_commission_settings( $post->ID ); + $commission->set_type( Fixed::SOURCE ); + + dokan()->product->save_commission_settings( + $post->ID, + [ + 'percentage' => $commission->get_percentage(), + 'type' => $commission->get_type(), + 'flat' => $commission->get_flat(), + ] + ); + } + + return true; + } +} diff --git a/includes/Upgrade/Upgrades/V_4_0_0.php b/includes/Upgrade/Upgrades/V_4_0_0.php new file mode 100644 index 0000000000..5994cce255 --- /dev/null +++ b/includes/Upgrade/Upgrades/V_4_0_0.php @@ -0,0 +1,140 @@ +commission->get_legacy_commission_types() ), true ) ) { + $options['commission_type'] = Fixed::SOURCE; + update_option( 'dokan_selling', $options ); + } + } + + /** + * Update global category commisions. + * + * @since DOKAN_SINCE + * + * @return void + */ + public static function update_global_category_commission_types() { + $has_categories = true; + $page_number = 1; + $processor = new V_4_0_0_UpdateCommissions(); + + while ( $has_categories ) { + $args = [ + 'taxonomy' => 'product_cat', + 'number' => 20, + 'orderby' => 'name', + 'order' => 'ASC', + 'hide_empty' => false, + 'offset' => ( $page_number - 1 ) * 20, + ]; + + $terms = get_terms( $args ); + + if ( empty( $terms ) ) { + $has_categories = false; + } else { + $args = [ + 'data' => $terms, + 'task' => 'global-commission', + ]; + $processor->push_to_queue( $args ); + } + + ++$page_number; + } + + $processor->dispatch_process(); + } + + /** + * Update vendor comission settings. + * + * @since DOKAN_SINCE + * + * @return void + */ + public static function update_category_commission_of_vendors() { + $page_number = 1; + $has_vendors = true; + $processor = new V_4_0_0_UpdateCommissions(); + + while ( $has_vendors ) { + $vendors = dokan()->vendor->all( + [ + 'paged' => $page_number, + ] + ); + + if ( empty( $vendors ) ) { + $has_vendors = false; + } else { + $args = [ + 'data' => $vendors, + 'task' => 'vendors-commission', + ]; + $processor->push_to_queue( $args ); + } + + ++$page_number; + } + + $processor->dispatch_process(); + } + + /** + * Update product commission settings. + * + * @since DOKAN_SINCE + * + * @return void + */ + public static function update_category_commission_of_products() { + $page_number = 1; + $has_products = true; + $processor = new V_4_0_0_UpdateCommissions(); + + while ( $has_products ) { + $products = dokan()->product->all( + [ + 'posts_per_page' => 10, + 'paged' => $page_number, + ] + ); + + $products = $products->posts; + + if ( empty( $products ) ) { + $has_products = false; + } else { + $args = [ + 'data' => $products, + 'task' => 'products-commission', + ]; + $processor->push_to_queue( $args ); + } + + ++$page_number; + } + + $processor->dispatch_process(); + } +} diff --git a/includes/Vendor/Manager.php b/includes/Vendor/Manager.php index 439442c6c5..95346741d6 100644 --- a/includes/Vendor/Manager.php +++ b/includes/Vendor/Manager.php @@ -325,6 +325,14 @@ public function update( $vendor_id, $data = [] ) { if ( isset( $data['admin_commission'] ) && ( is_numeric( wc_format_decimal( $data['admin_commission'] ) ) || '' === $data['admin_commission'] ) ) { $vendor->update_meta( 'dokan_admin_percentage', wc_format_decimal( $data['admin_commission'] ) ); } + + if ( isset( $data['admin_additional_fee'] ) && ( is_numeric( wc_format_decimal( $data['admin_additional_fee'] ) ) || '' === $data['admin_additional_fee'] ) ) { + $vendor->update_meta( 'dokan_admin_additional_fee', wc_format_decimal( $data['admin_additional_fee'] ) ); + } + + if ( isset( $data['admin_category_commission'] ) ) { + $vendor->update_meta( 'admin_category_commission', wc_clean( $data['admin_category_commission'] ) ); + } } // update vendor store data diff --git a/includes/Vendor/Vendor.php b/includes/Vendor/Vendor.php index 3449228979..6955a0d18d 100644 --- a/includes/Vendor/Vendor.php +++ b/includes/Vendor/Vendor.php @@ -5,9 +5,8 @@ use Automattic\WooCommerce\Utilities\NumberUtil; use WC_Order; use WeDevs\Dokan\Cache; -use WeDevs\Dokan\Product\ProductCache; +use WeDevs\Dokan\Commission\Model\Setting; use WP_Error; -use WP_Query; use WP_User; /** @@ -630,8 +629,6 @@ public function get_store_categories( $best_selling = false ) { // get extra information $display_type = get_term_meta( $term->term_id, 'display_type', true ); $thumbnail_id = absint( get_term_meta( $term->term_id, 'thumbnail_id', true ) ); - $category_commision_type = get_term_meta( $term->term_id, 'per_category_admin_commission_type', true ); - $category_commision = get_term_meta( $term->term_id, 'per_category_admin_commission', true ); $category_icon = get_term_meta( $term->term_id, 'dokan_cat_icon', true ); $category_icon_color = get_term_meta( $term->term_id, 'dokan_cat_icon_color', true ); @@ -645,9 +642,6 @@ public function get_store_categories( $best_selling = false ) { $image = $thumbnail = wc_placeholder_img_src(); } - // fix commission - $category_commision = ! empty( $category_commision ) ? wc_format_decimal( $category_commision ) : 0.00; - // set extra fields to term object $term->thumbnail = $thumbnail; $term->image = $image; @@ -655,9 +649,6 @@ public function get_store_categories( $best_selling = false ) { $term->icon = $category_icon; $term->icon_color = $category_icon_color; $term->display_type = $display_type; - // set commissions - $term->admin_commission_type = $category_commision_type; - $term->admin_commission = $category_commision; // finally store category data $all_categories[] = $term; @@ -943,17 +934,6 @@ public function get_readable_rating( $display = true ) { echo esc_html( $html ); } - /** - * Get vendor percentage - * - * @param integer $product_id - * - * @return integer - */ - public function get_percentage( $product_id = 0 ) { - return dokan_get_seller_percentage( $this->id, $product_id ); - } - /** * Make vendor active * @@ -1375,7 +1355,7 @@ protected function set_prop( $prop, $value ) { * @param string $key * @param bool $single Whether to return a single value * - * @return Mix + * @return mixed|null|false */ public function get_meta( $key, $single = false ) { return get_user_meta( $this->get_id(), $key, $single ); @@ -1567,6 +1547,32 @@ public function save() { $this->apply_changes(); } + /** + * Returns vendor commission settings data. + * + * @since DOKAN_SINCE + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function get_commission_settings() { + $settings = new \WeDevs\Dokan\Commission\Settings\Vendor( $this->get_id() ); + return $settings->get(); + } + + /** + * Saves commission settings. + * + * @since DOKAN_SINCE + * + * @param array $commission + * + * @return \WeDevs\Dokan\Commission\Model\Setting + */ + public function save_commission_settings( $commission = [] ) { + $settings = new \WeDevs\Dokan\Commission\Settings\Vendor( $this->get_id() ); + return $settings->save( $commission ); + } + /** * Get vendor profile url for admin * diff --git a/includes/Walkers/CategoryDropdownSingle.php b/includes/Walkers/CategoryDropdownSingle.php deleted file mode 100644 index eed9a56e57..0000000000 --- a/includes/Walkers/CategoryDropdownSingle.php +++ /dev/null @@ -1,56 +0,0 @@ - 'parent', - 'id' => 'term_id', - ); - - public function __construct( $post_id ) { - $this->post_id = $post_id; - parent::__construct( $post_id ); - } - - - public function start_el( &$output, $category, $depth = 0, $args = array(), $id = 0 ) { - if ( defined( 'DOKAN_PRO_PLUGIN_VERSION' ) && version_compare( DOKAN_PRO_PLUGIN_VERSION, '2.9.14', '<' ) ) { - $commission_val = dokan_get_seller_percentage( dokan_get_current_user_id(), $this->post_id, $category->term_id ); - $commission_type = dokan_get_commission_type( dokan_get_current_user_id(), $this->post_id, $category->term_id ); - } else { - $commission_val = dokan()->commission->get_earning_by_product( $this->post_id ); - - if ( is_wp_error( $commission_val ) ) { - $commission_val = 0; - } - } - - $pad = str_repeat( ' —', $depth * 1 ); - $cat_name = apply_filters( 'list_cats', $category->name, $category ); - $output .= "\t\n"; - } -} diff --git a/includes/Walkers/TaxonomyDropdown.php b/includes/Walkers/TaxonomyDropdown.php index 106a1359d6..43228aa7e5 100644 --- a/includes/Walkers/TaxonomyDropdown.php +++ b/includes/Walkers/TaxonomyDropdown.php @@ -51,16 +51,16 @@ public function __construct( $post_id = 0 ) { * @return void */ public function start_el( &$output, $category, $depth = 0, $args = [], $id = 0 ) { - if ( defined( 'DOKAN_PRO_PLUGIN_VERSION' ) && version_compare( DOKAN_PRO_PLUGIN_VERSION, '2.9.14', '<' ) ) { - $commission_val = dokan_get_seller_percentage( dokan_get_current_user_id(), $this->post_id, $category->term_id ); - $commission_type = dokan_get_commission_type( dokan_get_current_user_id(), $this->post_id, $category->term_id ); - } else { - $commission_val = dokan()->commission->get_earning_by_product( $this->post_id ); - - if ( is_wp_error( $commission_val ) ) { - $commission_val = 0; - } - } + $commission_data = dokan()->commission->get_commission( + [ + 'product_id' => $this->post_id, + 'category_id' => $category->term_id, + 'vendor_id' => dokan_get_current_user_id(), + ] + ); + + $commission_val = $commission_data->get_vendor_earning(); + $commission_type = $commission_data->get_type(); $pad = str_repeat( ' —', $depth * 1 ); $cat_name = apply_filters( 'list_cats', $category->name, $category ); diff --git a/includes/functions.php b/includes/functions.php index 5b1cfae3f6..95225e27ea 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -423,82 +423,25 @@ function dokan_author_pageviews( $seller_id ) { /** * Get store seller percentage settings * + * @deprecated DOKAN_SINCE Do Not Use This Function + * * @param int $seller_id * @param int $product_id * * @return int */ function dokan_get_seller_percentage( $seller_id = 0, $product_id = 0, $category_id = 0 ) { + wc_deprecated_function( __FUNCTION__, 'DOKAN_SINCE', 'dokan()->commission->get_commission()' ); - // Seller will get 100 percent if ( any_input_val < 0 || percentage_input_val > 100 ) - $commission_val = 100; - - //Global percentage - $global_percentage = dokan_get_option( 'admin_percentage', 'dokan_selling', 0 ); - - if ( $global_percentage !== '' && is_numeric( $global_percentage ) && $global_percentage >= 0 ) { - $global_type = dokan_get_option( 'commission_type', 'dokan_selling', 'percentage' ); - - if ( 'percentage' === $global_type ) { - if ( $global_percentage <= 100 ) { - $commission_val = (float) ( 100 - $global_percentage ); - } - } elseif ( 'flat' === $global_type ) { - $commission_val = (float) $global_percentage; - } - } - - //seller wise percentage - if ( $seller_id ) { - $admin_commission = get_user_meta( $seller_id, 'dokan_admin_percentage', true ); - - if ( $admin_commission !== '' && is_numeric( $admin_commission ) && $admin_commission >= 0 ) { - $admin_percentage_type = get_user_meta( $seller_id, 'dokan_admin_percentage_type', true ); - - if ( 'percentage' === $admin_percentage_type ) { - if ( $admin_commission <= 100 ) { - $commission_val = (float) ( 100 - $admin_commission ); - } - } elseif ( 'flat' === $admin_percentage_type ) { - $commission_val = (float) $admin_commission; - } - } - } - - //product and category wise percentage - if ( $product_id ) { - - //category wise percentage - $category_commission = dokan_get_category_wise_seller_commission( $product_id, $category_id ); - $is_single_category = dokan_get_option( 'product_category_style', 'dokan_selling', 'single' ); - - if ( $is_single_category === 'single' && $category_commission !== '' && is_numeric( $category_commission ) && $category_commission >= 0 ) { - $category_commission_type = dokan_get_category_wise_seller_commission_type( $product_id, $category_id ); - - if ( 'percentage' === $category_commission_type ) { - if ( $category_commission <= 100 ) { - $commission_val = (float) ( 100 - $category_commission ); - } - } elseif ( 'flat' === $category_commission_type ) { - $commission_val = (float) $category_commission; - } - } - - //product wise percentage - $_per_product_commission = get_post_meta( $product_id, '_per_product_admin_commission', true ); - - if ( $_per_product_commission !== '' && is_numeric( $_per_product_commission ) && $_per_product_commission >= 0 ) { - $_per_product_commission_type = get_post_meta( $product_id, '_per_product_admin_commission_type', true ); + $commission_data = dokan()->commission->get_commission( + [ + 'vendor_id' => $seller_id, + 'product_id' => $product_id, + 'category_id' => $category_id, + ] + ); - if ( 'percentage' === $_per_product_commission_type ) { - if ( $_per_product_commission <= 100 ) { - $commission_val = (float) ( 100 - $_per_product_commission ); - } - } elseif ( 'flat' === $_per_product_commission_type ) { - $commission_val = (float) $_per_product_commission; - } - } - } + $commission_val = $commission_data->get_vendor_earning(); return apply_filters( 'dokan_get_seller_percentage', $commission_val, $seller_id, $product_id ); } @@ -507,6 +450,8 @@ function dokan_get_seller_percentage( $seller_id = 0, $product_id = 0, $category /** * Get Dokan commission type by seller or product or both * + * @deprecated DOKAN_SINCE Do Not Use This Function + * * @since 2.6.9 * * @param int $seller_id @@ -515,48 +460,17 @@ function dokan_get_seller_percentage( $seller_id = 0, $product_id = 0, $category * @return string $type */ function dokan_get_commission_type( $seller_id = 0, $product_id = 0, $category_id = 0 ) { - //return product wise percentage - if ( $product_id ) { - $_per_product_commission = get_post_meta( $product_id, '_per_product_admin_commission', true ); - - if ( $_per_product_commission !== '' ) { - $type = get_post_meta( $product_id, '_per_product_admin_commission_type', true ); - $type = empty( $type ) ? 'percentage' : $type; - - if ( 'flat' === $type || ( 'percentage' === $type && $_per_product_commission <= 100 ) ) { - return $type; - } - } - - $category_commission = dokan_get_category_wise_seller_commission( $product_id, $category_id ); + wc_deprecated_function( __FUNCTION__, 'DOKAN_SINCE', 'dokan()->commission->get_commission()' ); - if ( ! empty( $category_commission ) && $category_commission ) { - $type = dokan_get_category_wise_seller_commission_type( $product_id, $category_id ); - $type = empty( $type ) ? 'percentage' : $type; - - if ( 'flat' === $type || ( 'percentage' === $type && $category_commission <= 100 ) ) { - return $type; - } - } - } - - //return seller wise percentage - if ( $seller_id ) { - $admin_commission = get_user_meta( $seller_id, 'dokan_admin_percentage', true ); - - if ( $admin_commission !== '' ) { - $type = get_user_meta( $seller_id, 'dokan_admin_percentage_type', true ); - $type = empty( $type ) ? 'percentage' : $type; - - if ( 'flat' === $type || ( 'percentage' === $type && $admin_commission <= 100 ) ) { - return $type; - } - } - } - - $global_type = dokan_get_option( 'commission_type', 'dokan_selling', 'percentage' ); + $commission_data = dokan()->commission->get_commission( + [ + 'vendor_id' => $seller_id, + 'product_id' => $product_id, + 'category_id' => $category_id, + ] + ); - return $global_type; + return $commission_data->get_type(); } /** @@ -1077,7 +991,8 @@ function dokan_edit_product_url( $product, bool $is_new_product = false ) { * @return array */ function dokan_admin_product_columns( $columns ) { - $columns['author'] = __( 'Author', 'dokan-lite' ); + $columns['admin_commission'] = __( 'Commission', 'dokan-lite' ); + $columns['author'] = __( 'Author', 'dokan-lite' ); return $columns; } @@ -2653,7 +2568,9 @@ function dokan_register_store_widget() { add_action( 'widgets_init', 'dokan_register_store_widget' ); /** - * Calculate category wise commission for given product + * Calculate category wise commission for given product. + * + * @deprecated DOKAN_SINCE Do Not Use This Function * * @since 2.6.8 * @@ -2662,34 +2579,15 @@ function dokan_register_store_widget() { * @return int $commission_rate */ function dokan_get_category_wise_seller_commission( $product_id, $category_id = 0 ) { - $terms = get_the_terms( $product_id, 'product_cat' ); - - if ( empty( $terms ) ) { - return 0; - } - - $term_id = $terms[0]->term_id; - - $category_commision = null; - - if ( $category_id ) { - $terms = get_term( $category_id ); - $term_id = $terms->term_id; - } - - if ( $terms ) { - $category_commision = get_term_meta( $term_id, 'per_category_admin_commission', true ); - } - - if ( ! empty( $category_commision ) ) { - return wc_format_decimal( $category_commision ); - } + wc_deprecated_function( __FUNCTION__, 'DOKAN_SINCE' ); return 0; } /** - * Calculate category wise commission type for given product + * Calculate category wise commission type for given product. + * + * @deprecated DOKAN_SINCE Do Not Use This Function * * @since 2.6.9 * @@ -2698,20 +2596,9 @@ function dokan_get_category_wise_seller_commission( $product_id, $category_id = * @return int $commission_rate */ function dokan_get_category_wise_seller_commission_type( $product_id, $category_id = 0 ) { - $terms = get_the_terms( $product_id, 'product_cat' ); - $term_id = $terms[0]->term_id; - $category_commision = ''; - - if ( $category_id ) { - $terms = get_term( $category_id ); - $term_id = $terms->term_id; - } + wc_deprecated_function( __FUNCTION__, 'DOKAN_SINCE' ); - if ( $terms ) { - $category_commision = get_term_meta( $term_id, 'per_category_admin_commission_type', true ); - } - - return $category_commision; + return ''; } /** @@ -3191,6 +3078,8 @@ function dokan_remove_hook_for_anonymous_class( $hook_name = '', $class_name = ' /** * Dokan get variable product earnings * + * @deprecated 2.9.21 + * * @param int $product_id * @param bool $formated * @param bool $deprecated @@ -3364,8 +3253,8 @@ function dokan_privacy_policy_text( $return = false ) { function dokan_commission_types() { return apply_filters( 'dokan_commission_types', [ - 'flat' => __( 'Flat', 'dokan-lite' ), - 'percentage' => __( 'Percentage', 'dokan-lite' ), + 'fixed' => __( 'Fixed', 'dokan-lite' ), + 'category_based' => __( 'Category Based', 'dokan-lite' ), ] ); } diff --git a/includes/wc-template.php b/includes/wc-template.php index bca7bece9e..9b3b2d5410 100755 --- a/includes/wc-template.php +++ b/includes/wc-template.php @@ -217,9 +217,27 @@ function dokan_vendor_quick_edit_data( $column, $post_id ) { commission->get_earning_by_product( $post_id, 'admin' ); + echo is_numeric( $commission ) ? wc_price( $commission ) : ''; + + break; + default: break; } + + ?> + + -
-
- - {{ '%' }} -
-
- {{ '+' }} -
-
- {{ getCurrencySymbol }} - -
+
+
+ +
+ {{ __( '%', 'dokan-lite' ) }}
+
+ {{ __( '+', 'dokan-lite' ) }} +
+
+
+ {{ getCurrencySymbol }}
+ +
+
- diff --git a/src/admin/components/Commission/CategoryBasedCommission.vue b/src/admin/components/Commission/CategoryBasedCommission.vue new file mode 100644 index 0000000000..754e0eaf35 --- /dev/null +++ b/src/admin/components/Commission/CategoryBasedCommission.vue @@ -0,0 +1,365 @@ + + + + + diff --git a/src/admin/components/Commission/index.js b/src/admin/components/Commission/index.js new file mode 100644 index 0000000000..aa3357bf63 --- /dev/null +++ b/src/admin/components/Commission/index.js @@ -0,0 +1 @@ +import './style.css'; diff --git a/src/admin/components/Commission/style.css b/src/admin/components/Commission/style.css new file mode 100644 index 0000000000..c38c0f161c --- /dev/null +++ b/src/admin/components/Commission/style.css @@ -0,0 +1,4 @@ +@config './tailwind-category-commission.config.js'; +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/src/admin/components/Commission/tailwind-category-commission.config.js b/src/admin/components/Commission/tailwind-category-commission.config.js new file mode 100644 index 0000000000..063f70ff4f --- /dev/null +++ b/src/admin/components/Commission/tailwind-category-commission.config.js @@ -0,0 +1,20 @@ +/** @type {import('tailwindcss').Config} */ +const defaultTheme = require("tailwindcss/defaultTheme"); +module.exports = { + corePlugins: { + preflight: false, + }, + content: [ + './src/admin/components/Commission/CategoryBasedCommission.vue', + './src/admin/components/CombineInput.vue', + ], + theme: { + extend: { + screens: { + ...defaultTheme.screens, + 'd-xs': '360px', + } + } + }, + plugins: [], +}; diff --git a/src/admin/components/Currency.vue b/src/admin/components/Currency.vue index 9a3c4268af..9ec4fc48fe 100644 --- a/src/admin/components/Currency.vue +++ b/src/admin/components/Currency.vue @@ -8,7 +8,7 @@ export default { methods: { formattedPrice(value) { - return accounting.formatMoney( value, dokan.currency ); + return accounting.formatMoney( value, {...dokan.currency, precision: dokan.currency.precision+ 2} ); } } }; diff --git a/src/admin/components/Fields.vue b/src/admin/components/Fields.vue index e3646fdb5f..4210fab88d 100644 --- a/src/admin/components/Fields.vue +++ b/src/admin/components/Fields.vue @@ -72,58 +72,17 @@
- - -