Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: Make analytics reports compatible with Dokan #2318

Open
wants to merge 78 commits into
base: develop
Choose a base branch
from

Conversation

mrabbani
Copy link
Member

@mrabbani mrabbani commented Jul 25, 2024

All Submissions:

  • My code follow the WordPress' coding standards
  • My code satisfies feature requirements
  • My code is tested
  • My code passes the PHPCS tests
  • My code has proper inline documentation
  • I've included related pull request(s) (optional)
  • I've included developer documentation (optional)
  • I've added proper labels to this pull request

Changes proposed in this Pull Request:

Related Pull Request(s)

  • Full PR Link

Closes

  • Closes #

How to test the changes in this Pull Request:

  • Steps or issue link

Changelog entry

Title

Detailed Description of the pull request. What was previous behaviour
and what will be changed in this PR.

Before Changes

Describe the issue before changes with screenshots(s).

After Changes

Describe the issue after changes with screenshot(s).

Feature Video (optional)

Link of detailed video if this PR is for a feature.

PR Self Review Checklist:

  • Code is not following code style guidelines
  • Bad naming: make sure you would understand your code if you read it a few months from now.
  • KISS: Keep it simple, Sweetie (not stupid!).
  • DRY: Don't Repeat Yourself.
  • Code that is not readable: too many nested 'if's are a bad sign.
  • Performance issues
  • Complicated constructions that need refactoring or comments: code should almost always be self-explanatory.
  • Grammar errors.

FOR PR REVIEWER ONLY:

As a reviewer, your feedback should be focused on the idea, not the person. Seek to understand, be respectful, and focus on constructive dialog.

As a contributor, your responsibility is to learn from suggestions and iterate your pull request should it be needed based on feedback. Seek to collaborate and produce the best possible contribution to the greater whole.

  • Correct — Does the change do what it’s supposed to? ie: code 100% fulfilling the requirements?
  • Secure — Would a nefarious party find some way to exploit this change? ie: everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities?
  • Readable — Will your future self be able to understand this change months down the road?
  • Elegant — Does the change fit aesthetically within the overall style and architecture?

Summary by CodeRabbit

  • New Features

    • Enhanced dependency management with improved autoloading for third-party packages.
    • Introduced advanced analytics reporting tailored for multi-vendor marketplaces, including stock and order statistics.
    • Added new service providers for managing common and analytics-related services, improving modularity.
    • Implemented a new database table for order statistics to enhance data management and reporting.
    • Introduced classes for filtering and customizing WooCommerce analytics queries, enhancing reporting capabilities.
    • Streamlined order processing by removing child order management functionality.
  • Bug Fixes

    • Disabled specific hooks related to WooCommerce order processing and analytics to prevent unintended behavior.
  • Documentation

    • Updated documentation to reflect new features and provide usage scenarios for the analytics system.
  • Chores

    • Improved modularity and maintainability through refactoring of the service provider architecture.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Outside diff range, codebase verification and nitpick comments (1)
includes/Analytics/Reports/Customers/QueryFilter.php (1)

24-28: Consider removing or uncommenting code.

There are several commented-out lines of code. If these are not needed, consider removing them for clarity.

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 707259d and afaa5bd.

Files selected for processing (8)
  • docs/analytics/reports.md (1 hunks)
  • includes/Analytics/Reports/Coupons/QueryFilter.php (1 hunks)
  • includes/Analytics/Reports/Coupons/Stats/QueryFilter.php (1 hunks)
  • includes/Analytics/Reports/Customers/QueryFilter.php (1 hunks)
  • includes/Analytics/Reports/Customers/Stats/QueryFilter.php (1 hunks)
  • includes/Analytics/Reports/OrderType.php (1 hunks)
  • includes/Analytics/Reports/Products/Stats/QueryFilter.php (1 hunks)
  • includes/DependencyManagement/Providers/AnalyticsServiceProvider.php (1 hunks)
Files skipped from review as they are similar to previous changes (5)
  • includes/Analytics/Reports/Coupons/QueryFilter.php
  • includes/Analytics/Reports/Coupons/Stats/QueryFilter.php
  • includes/Analytics/Reports/OrderType.php
  • includes/Analytics/Reports/Products/Stats/QueryFilter.php
  • includes/DependencyManagement/Providers/AnalyticsServiceProvider.php
Additional context used
Markdownlint
docs/analytics/reports.md

2-2: null
Link fragments should be valid

(MD051, link-fragments)

Additional comments not posted (3)
docs/analytics/reports.md (1)

1-19: Well-structured documentation.

The documentation provides a clear and concise guide for handling Dokan orders and customizing the WooCommerce analytics datastore.

Tools
Markdownlint

2-2: null
Link fragments should be valid

(MD051, link-fragments)

includes/Analytics/Reports/Customers/QueryFilter.php (1)

12-64: LGTM!

The implementation of the QueryFilter class is well-structured and correctly utilizes WordPress hooks to modify WooCommerce analytics queries.

includes/Analytics/Reports/Customers/Stats/QueryFilter.php (1)

7-80: Well-implemented class for query filtering.

The QueryFilter class effectively extends the functionality of CustomersQueryFilter with clear logic for modifying SQL clauses.

@@ -0,0 +1,19 @@
- [Introduction](#introduction)
- [Custom Products Stats Datastore](#custom-products-stats-datastore)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix the link fragment in the table of contents.

The link fragment for "Custom Products Stats Datastore" should match the section heading.

- [Custom Products Stats Datastore](#custom-products-stats-datastore)
+ [Custom Stats Datastore](#custom-stats-datastore)
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [Custom Products Stats Datastore](#custom-products-stats-datastore)
[Custom Stats Datastore](#custom-stats-datastore)
Tools
Markdownlint

2-2: null
Link fragments should be valid

(MD051, link-fragments)

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between afaa5bd and 0176baf.

Files selected for processing (2)
  • dokan-class.php (1 hunks)
  • includes/DependencyManagement/Providers/CommonServiceProvider.php (1 hunks)
Files skipped from review as they are similar to previous changes (2)
  • dokan-class.php
  • includes/DependencyManagement/Providers/CommonServiceProvider.php

@mrabbani mrabbani mentioned this pull request Aug 21, 2024
12 tasks
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 0176baf and d3fa0f1.

Files selected for processing (2)
  • includes/Analytics/Reports/BaseQueryFilter.php (1 hunks)
  • tests/php/src/Analytics/Reports/Orders/QueryFilterTest.php (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • tests/php/src/Analytics/Reports/Orders/QueryFilterTest.php
Additional context used
GitHub Check: Run PHPCS inspection
includes/Analytics/Reports/BaseQueryFilter.php

[warning] 70-70:
Processing form data without nonce verification.

Additional comments not posted (2)
includes/Analytics/Reports/BaseQueryFilter.php (2)

14-24: Constructor and hook registration are well-implemented.

The constructor method correctly initializes the class and registers hooks, adhering to good OOP practices and WordPress standards.


87-89: Method implementation is straightforward and clear.

The should_filter_by_seller_id method is implemented correctly and serves its purpose without any apparent issues.

Comment on lines +33 to +41
public function add_join_subquery( array $clauses ): array {
global $wpdb;

$dokan_order_state_table = $this->get_dokan_table();

$clauses[] = "JOIN {$dokan_order_state_table} ON {$wpdb->prefix}{$this->wc_table}.order_id = {$dokan_order_state_table}.order_id";

return array_unique( $clauses );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure SQL injection prevention in JOIN clause.

The method dynamically constructs a JOIN clause which could be vulnerable to SQL injection if not properly sanitized.

Consider using $wpdb->prepare to ensure that the table names are safely included in the query.

Comment on lines +50 to +60
public function add_where_subquery( array $clauses ): array {
$dokan_order_state_table = $this->get_dokan_table();
$order_types = $this->get_order_and_refund_types_to_include();

$clauses[] = "AND {$dokan_order_state_table}.order_type in ( $order_types ) ";

$clauses = $this->add_where_subquery_for_refund( $clauses );
$clauses = $this->add_where_subquery_for_seller_filter( $clauses );

return array_unique( $clauses );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security concern: Potential SQL injection in WHERE clause.

The method constructs SQL conditions using unescaped data. This could lead to SQL injection vulnerabilities.

Use parameterized queries or $wpdb->prepare to ensure data is safely included.

Comment on lines +69 to +79
protected function add_where_subquery_for_refund( array $clauses ): array {
if ( ! isset( $_GET['refunds'] ) ) {
return $clauses;
}

$dokan_order_state_table = $this->get_dokan_table();
$order_types = $this->get_refund_types_to_include();

$clauses[] = "AND {$dokan_order_state_table}.order_type in ( $order_types ) ";

return $clauses;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Address CSRF vulnerability by adding nonce verification.

The method uses a GET parameter to modify the database query, which should be accompanied by nonce verification to prevent CSRF attacks.

Implement nonce verification when processing the 'refunds' GET parameter.

Would you like me to generate a code snippet for nonce verification?

Tools
GitHub Check: Run PHPCS inspection

[warning] 70-70:
Processing form data without nonce verification.

Comment on lines 168 to 178
protected function get_seller_id() {
if ( ! is_user_logged_in() ) {
return 0;
}

if ( ! current_user_can( 'manage_options' ) ) {
return dokan_get_current_user_id();
}

return (int) ( wp_unslash( $_GET['seller'] ?? 0 ) ); // phpcs:ignore
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure proper sanitization and validation of user input.

The method retrieves the seller ID from a GET parameter. Ensure that this value is properly sanitized and validated to prevent security issues.

Consider using more rigorous sanitization for the 'seller' GET parameter to ensure it is safe to use in queries.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between d3fa0f1 and 7366a46.

Files selected for processing (2)
  • includes/Analytics/Reports/BaseQueryFilter.php (1 hunks)
  • tests/php/src/Analytics/Reports/Orders/QueryFilterTest.php (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • tests/php/src/Analytics/Reports/Orders/QueryFilterTest.php
Additional context used
GitHub Check: Run PHPCS inspection
includes/Analytics/Reports/BaseQueryFilter.php

[warning] 70-70:
Processing form data without nonce verification.

Additional comments not posted (11)
includes/Analytics/Reports/BaseQueryFilter.php (11)

22-24: LGTM!

The constructor is correctly implemented.

The code changes are approved.


33-41: Ensure SQL injection prevention in JOIN clause.

The method dynamically constructs a JOIN clause which could be vulnerable to SQL injection if not properly sanitized.

Consider using $wpdb->prepare to ensure that the table names are safely included in the query.


50-60: Security concern: Potential SQL injection in WHERE clause.

The method constructs SQL conditions using unescaped data. This could lead to SQL injection vulnerabilities.

Use parameterized queries or $wpdb->prepare to ensure data is safely included.


69-79: Address CSRF vulnerability by adding nonce verification.

The method uses a GET parameter to modify the database query, which should be accompanied by nonce verification to prevent CSRF attacks.

Implement nonce verification when processing the 'refunds' GET parameter.

Would you like me to generate a code snippet for nonce verification?

Tools
GitHub Check: Run PHPCS inspection

[warning] 70-70:
Processing form data without nonce verification.


87-89: LGTM!

The method is correctly implemented.

The code changes are approved.


96-104: LGTM!

The method is correctly implemented.

The code changes are approved.


111-119: LGTM!

The method is correctly implemented.

The code changes are approved.


121-123: LGTM!

The method is correctly implemented.

The code changes are approved.


130-138: LGTM!

The method is correctly implemented.

The code changes are approved.


147-161: Ensure SQL injection prevention in WHERE clause.

The method dynamically constructs a WHERE clause which could be vulnerable to SQL injection if not properly sanitized.

Consider using $wpdb->prepare to ensure that the data is safely included in the query.


168-178: Ensure proper sanitization and validation of user input.

The method retrieves the seller ID from a GET parameter. Ensure that this value is properly sanitized and validated to prevent security issues.

Consider using more rigorous sanitization for the 'seller' GET parameter to ensure it is safe to use in queries.

@mrabbani mrabbani added Needs: Testing This requires further testing and removed In Progress The issues is being worked on labels Sep 13, 2024
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Outside diff range and nitpick comments (3)
tests/php/src/Analytics/Reports/Stock/ProductQueryFilterTest.php (2)

13-33: LGTM! Consider adding an assertion for the actual product IDs.

The test method is correctly testing the scenario where the stock reports are fetched with a seller filter. However, consider adding an assertion to check that the response data contains the exact product IDs created for seller_id1.

 foreach ( $data as $item ) {
     $prod = wc_get_product( $item['id'] );
 }
 
 $this->assertCount( count( $seller1_prod_ids ), $data );
+$this->assertEqualsCanonicalizing( $seller1_prod_ids, array_column( $data, 'id' ) );

35-53: LGTM! Consider adding an assertion for the actual product IDs.

The test method is correctly testing the scenario where the stock reports are fetched without a seller filter. However, consider adding an assertion to check that the response data contains the exact product IDs created for both sellers.

 foreach ( $data as $item ) {
     $prod = wc_get_product( $item['id'] );
 }
 
 $this->assertCount( count( $seller1_prod_ids ) + count( $seller2_prod_ids ), $data );
+$this->assertEqualsCanonicalizing( array_merge( $seller1_prod_ids, $seller2_prod_ids ), array_column( $data, 'id' ) );
includes/Analytics/Reports/BaseQueryFilter.php (1)

168-178: Consider additional sanitization for the 'seller' GET parameter.

The method retrieves the seller ID from the 'sellers' GET parameter and casts it to an integer, which is an improvement from the previous version. However, consider using more rigorous sanitization measures to ensure the value is safe to use in queries.

For example, you could use absint to ensure the value is a non-negative integer:

-return (int) ( wp_unslash( $_GET['sellers']  ?? 0 ) ); // phpcs:ignore
+return absint( wp_unslash( $_GET['sellers'] ?? 0 ) ); // phpcs:ignore
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 7366a46 and 6f13a6e.

Files selected for processing (8)
  • includes/Analytics/Reports/BaseQueryFilter.php (1 hunks)
  • includes/Analytics/Reports/DataStoreModifier.php (1 hunks)
  • includes/Analytics/Reports/Products/Stats/WcDataStore.php (1 hunks)
  • includes/Analytics/Reports/Stock/QueryFilter.php (1 hunks)
  • includes/Analytics/Reports/Stock/Stats/WcDataStore.php (1 hunks)
  • includes/DependencyManagement/Providers/AnalyticsServiceProvider.php (1 hunks)
  • tests/php/src/Analytics/Reports/Stock/ProductQueryFilterTest.php (1 hunks)
  • tests/php/src/Analytics/Reports/Stock/Stats/QueryFilterTest.php (1 hunks)
Additional comments not posted (24)
includes/Analytics/Reports/Products/Stats/WcDataStore.php (1)

18-26: LGTM! The method is well-structured and follows best practices.

The initialize_queries() method is overriding the parent class's method to customize the query behavior. The use of the WcSqlQuery class instead of the SqlQuery class is justified in the comments, explaining the need for applying specific filters to the queries.

The method follows best practices by:

  • Using the get_db_table_name() method to get the database table name, which is good for maintainability.
  • Using the add_sql_clause() method to add clauses to the queries, which is a clean and readable way of building the queries.
  • Using the clear_all_clauses() method to clear all clauses before initializing the queries, which ensures that the queries are built from scratch.

The method is well-structured and follows the Single Responsibility Principle (SRP) by focusing on initializing the queries.

includes/Analytics/Reports/Stock/QueryFilter.php (2)

12-14: LGTM!

The register_hooks() method is correctly registering the check_wc_analytics_reports_stock_path filter hook with the appropriate priority and number of arguments.


39-52: LGTM!

The add_author_clause() method is correctly modifying the SQL WHERE clause to filter by seller ID. It has proper documentation and the logic is sound.

tests/php/src/Analytics/Reports/Stock/Stats/QueryFilterTest.php (2)

12-30: LGTM!

The test method is well-structured, follows the AAA pattern, and correctly tests the stock stats report for all sellers. The test method name is descriptive and follows the naming convention.


32-52: LGTM!

The test method is well-structured, follows the AAA pattern, and correctly tests the stock stats report filtered by a seller. The test method name is descriptive and follows the naming convention.

includes/Analytics/Reports/DataStoreModifier.php (3)

10-10: LGTM!

The DataStoreModifier class follows SOLID principles and has a clear purpose.


19-21: LGTM!

The register_hooks method correctly registers the filter to modify WooCommerce data stores.


35-57: LGTM!

The modify_wc_products_stats_datastore method follows the Open-Closed Principle and has a clear purpose. The use of isset to avoid undefined index notices is a good practice. The docblock provides a clear explanation of the modifications and their reason.

includes/DependencyManagement/Providers/AnalyticsServiceProvider.php (4)

11-31: LGTM!

The AnalyticsServiceProvider class is well-structured and follows the expected conventions for a service provider in a dependency injection system. The class definition, TAGS constant, and $services property are all properly defined.


41-43: LGTM!

The provides method is implemented correctly. It checks if the given service alias exists in the $services property or TAGS constant and returns a boolean accordingly. The use of strict comparison with in_array is a good practice.


48-58: LGTM!

The register method is implemented correctly. It loops through the $services property and registers each service with the container using a shared definition. It also adds the tags defined in the TAGS constant to each service definition. This approach is readable, maintainable, and allows for flexibility in retrieving services from the container.


60-64: LGTM!

The add_tags method is a well-defined private helper method. It accepts a DefinitionInterface parameter and a $tags parameter, ensuring type safety. The method correctly loops through the $tags and adds each tag to the given service definition using the addTag method. This implementation is clean and follows the expected behavior.

includes/Analytics/Reports/BaseQueryFilter.php (6)

87-89: LGTM!

The method correctly indicates that the query should always be filtered by seller ID.


96-104: LGTM!

The method correctly retrieves the order types to include in WooCommerce analytics queries based on the user role.


111-119: LGTM!

The method correctly retrieves the refund types to include in WooCommerce analytics queries based on the user role.


121-123: LGTM!

The method correctly retrieves the name of the Dokan table.


130-138: LGTM!

The method correctly retrieves the non-refund order types to include in WooCommerce analytics queries based on the user role.


147-161: LGTM!

The method correctly adds a where clause to filter the query by the seller ID when available. The SQL condition is properly prepared using $wpdb->prepare to prevent SQL injection.

includes/Analytics/Reports/Stock/Stats/WcDataStore.php (6)

14-57: LGTM!

The get_data method is well-implemented and effectively uses transients for caching stock counts. The use of seller-specific transient keys ensures that the cached data is specific to each seller. The method handles the case when the transient is not set and retrieves the data from the database. The use of the wc_get_product_stock_status_options function ensures compatibility with WooCommerce.


64-101: LGTM!

The get_low_stock_count method is well-implemented and correctly retrieves the count of products with low stock. The method handles the case when the low stock amount meta value is not set by using the default low stock amount option. The SQL query is well-structured and uses prepared statements to prevent SQL injection vulnerabilities. The use of the get_seller_where_query method ensures that the low stock count is specific to each seller.


109-125: LGTM!

The get_count method is well-implemented and correctly retrieves the count of products with a specific stock status. The SQL query is simple and uses prepared statements to prevent SQL injection vulnerabilities. The use of the get_seller_where_query method ensures that the count is specific to each seller.


132-145: LGTM!

The get_product_count method is well-implemented and correctly retrieves the total count of products for the store. The method uses the WP_Query class, which is a standard WordPress approach. It correctly handles the case when a seller ID is available by adding the seller-specific condition to the query arguments. The use of intval ensures that the returned count is an integer value.


147-149: LGTM!

The get_seller_id method is concise and well-implemented. It uses the Dokan container to retrieve the seller ID from the WeDevs\Dokan\Analytics\Reports\Stock\QueryFilter class, which is a good practice for dependency injection. The method casts the seller ID to an integer using (int) to ensure that it returns an integer value.


151-165: LGTM!

The get_seller_where_query method is well-implemented and correctly generates the seller-specific WHERE clause for SQL queries. It retrieves the seller ID using the get_seller_id method and generates a prepared SQL statement to add the seller-specific condition to the WHERE clause. The use of prepared statements ensures that the SQL query is secure and prevents SQL injection vulnerabilities. The method returns an empty string if no seller ID is available, which allows the queries to work correctly without the seller-specific condition.

Comment on lines +16 to +23
/**
* Undocumented function
*
* @param [type] $result
* @param [type] $server
* @param WP_REST_Request $request
* @return mixed
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add proper documentation for the check_wc_analytics_reports_stock_path() method.

The method is missing proper documentation. Please add a clear description of what the method does, the purpose of its parameters, and the expected return value.

Copy link
Member Author

@mrabbani mrabbani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo

  • Run migration to resync the analytics Data.
  • What will be happen if the dokan stats table is not created but trying to sync the order.
  • Add admin_shipping_fee and seller_shipping_fee cols in the dokan_order_stats table.

includes/Analytics/Reports/Orders/Stats/DataStore.php Outdated Show resolved Hide resolved
*/
public function register_hooks(): void {
add_action( 'woocommerce_analytics_update_order_stats', [ $this, 'sync_dokan_order' ] );
add_action( 'woocommerce_before_delete_order', [ $this, 'delete_order' ] );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we delete stats?

Yes

  • Report will be mismatch with the dokan_vendor_balance.

No

  • Report will not be synced as per WC stats data.

* @param string $handling Optional. The handling mode for the clause. Defaults to an empty string.
* @return string The SQL clause.
*/
protected function get_sql_clause( $type, $handling = '' ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default params should be a valid value

@@ -536,4 +537,26 @@ private static function parse_update_notice( $content, $new_version ) {

return wp_kses_post( $upgrade_notice );
}

protected function create_dokan_order_stats_table() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will be happened for exist Dokan User?

$customer_id = absint( CustomersDataStore::get_existing_customer_id_from_order( $order ) );

// Delete the order.
$wpdb->delete( self::get_db_table_name(), array( 'order_id' => $order_id ) );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will be happened if table does not exist for existing Dokan?

);

// Update or add the information to the DB.
$result = $wpdb->replace( $table_name, $data, $format );
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will be happened if table does not exist for existing Dokan?

includes/Order/MiscHooks.php Outdated Show resolved Hide resolved
includes/Order/MiscHooks.php Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Outside diff range and nitpick comments (3)
includes/Analytics/Reports/Orders/Stats/DataStore.php (1)

65-65: Remove commented-out code if not needed

The line setting $this->date_column_name is commented out. If this code is no longer necessary, consider removing it to keep the code clean. If it's required, please uncomment it and ensure it functions as intended.

includes/Install/Installer.php (2)

542-542: Improve the clarity of the comment.

The comment on line 542 has grammatical errors and could be clearer. Consider rephrasing it for better understanding:

-// Following imported here because this method could be called from the others file.
+// The following is included here because this method could be called from other files.

548-549: Ensure consistent data type declarations for bigint columns.

For consistency with other table definitions, consider specifying the display width for bigint columns:

-`order_id` bigint UNSIGNED NOT NULL,
-`seller_id` bigint UNSIGNED NOT NULL DEFAULT '0',
+`order_id` bigint(20) UNSIGNED NOT NULL,
+`seller_id` bigint(20) UNSIGNED NOT NULL DEFAULT '0',
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 6f13a6e and 0d84346.

📒 Files selected for processing (4)
  • includes/Analytics/Reports/Orders/Stats/DataStore.php (1 hunks)
  • includes/Analytics/Reports/WcSqlQuery.php (1 hunks)
  • includes/Install/Installer.php (2 hunks)
  • includes/Order/MiscHooks.php (0 hunks)
💤 Files with no reviewable changes (1)
  • includes/Order/MiscHooks.php
🔇 Additional comments (4)
includes/Analytics/Reports/WcSqlQuery.php (4)

3-5: LGTM: Namespace and use statement are correctly defined.

The namespace WeDevs\Dokan\Analytics\Reports is properly defined and follows PSR-4 autoloading standards. The use statement correctly imports the parent class SqlQuery from the WooCommerce Admin API Reports.


7-7: LGTM: Class definition and inheritance are correct.

The WcSqlQuery class is properly defined and correctly extends the SqlQuery class from WooCommerce Admin API Reports. The class name follows the appropriate naming convention.


8-15: LGTM: Method documentation is clear and follows PHPDoc standards.

The documentation for the get_sql_clause method is well-written and informative. It clearly explains the purpose of changing the default value of the $handling parameter and provides accurate descriptions of the parameters and return value. The documentation follows the PHPDoc standard, which enhances code readability and maintainability.


16-18: LGTM: Method implementation is correct and addresses the previous review comment.

The get_sql_clause method is correctly overridden and implements the intended change in the default value of the $handling parameter. The implementation is concise and properly delegates to the parent class's method.

This change addresses the previous review comment about default parameters having valid values. The new default value 'filtered' is a valid and meaningful value for this context.

Comment on lines +23 to +24
* Max allowed Attemption to create table.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in comment: "Attemption" should be "Attempts"

In the comment, the word "Attemption" is incorrect. Please correct it to "Attempts" for proper grammar.

Comment on lines +28 to +31
* Attemption count to create order table if DB throws error.
*
* @var integer
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo in comment: "Attemption" should be "Attempt"

Similarly, in this comment, "Attemption" should be "Attempt" to correct the grammatical error.

Comment on lines 234 to 236
if ( $wpdb->last_error
&& str_contains( (string) $wpdb->last_error, "{$table_name}' doesn't exist" )
&& self::MAX_ATTEMPT > self::$attempt_count
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Replace str_contains with strpos for PHP compatibility

The str_contains function is only available in PHP 8 and above. To maintain compatibility with earlier PHP versions (e.g., PHP 7.x), consider using strpos instead.

Apply this diff to fix the compatibility issue:

-&& str_contains( (string) $wpdb->last_error, "{$table_name}' doesn't exist" )
+&& false !== strpos( (string) $wpdb->last_error, "{$table_name}' doesn't exist" )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ( $wpdb->last_error
&& str_contains( (string) $wpdb->last_error, "{$table_name}' doesn't exist" )
&& self::MAX_ATTEMPT > self::$attempt_count
if ( $wpdb->last_error
&& false !== strpos( (string) $wpdb->last_error, "{$table_name}' doesn't exist" )
&& self::MAX_ATTEMPT > self::$attempt_count

$sql = "CREATE TABLE IF NOT EXISTS `{$wpdb->prefix}dokan_order_stats` (
`order_id` bigint UNSIGNED NOT NULL,
`seller_id` bigint UNSIGNED NOT NULL DEFAULT '0',
`order_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 = WC Order, 1 = Dokan Single Vendor Order, 2 = Dokan Suborder, 3 = Refund of Dokan Parent Order, 4 = Refund of Dokan Suborder, 5 = 4 = Refund of Dokan Single Order',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Correct the typographical error in the order_type column comment.

The comment for the order_type column contains a duplicate numbering and should be corrected to accurately reflect the order types:

-`order_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 = WC Order, 1 = Dokan Single Vendor Order, 2 = Dokan Suborder, 3 = Refund of Dokan Parent Order, 4 = Refund of Dokan Suborder, 5 =  4 = Refund of Dokan Single Order',
+`order_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 = WC Order, 1 = Dokan Single Vendor Order, 2 = Dokan Suborder, 3 = Refund of Dokan Parent Order, 4 = Refund of Dokan Suborder, 5 = Refund of Dokan Single Order',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`order_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 = WC Order, 1 = Dokan Single Vendor Order, 2 = Dokan Suborder, 3 = Refund of Dokan Parent Order, 4 = Refund of Dokan Suborder, 5 = 4 = Refund of Dokan Single Order',
`order_type` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0 = WC Order, 1 = Dokan Single Vendor Order, 2 = Dokan Suborder, 3 = Refund of Dokan Parent Order, 4 = Refund of Dokan Suborder, 5 = Refund of Dokan Single Order',

Comment on lines +551 to +559
`seller_earning` double NOT NULL DEFAULT '0',
`seller_gateway_fee` double NOT NULL DEFAULT '0',
`seller_shipping_fee` double NOT NULL DEFAULT '0',
`seller_discount` double NOT NULL DEFAULT '0',
`admin_commission` double NOT NULL DEFAULT '0',
`admin_gateway_fee` double NOT NULL DEFAULT '0',
`admin_shipping_fee` double NOT NULL DEFAULT '0',
`admin_discount` double NOT NULL DEFAULT '0',
`admin_subsidy` double NOT NULL DEFAULT '0',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Use DECIMAL data type for monetary values instead of double.

Storing monetary values as double can lead to precision and rounding errors due to floating-point representation. It's recommended to use DECIMAL(19,4) for monetary amounts to ensure accuracy and consistency.

Apply this diff to update the data types:

-`seller_earning` double NOT NULL DEFAULT '0',
-`seller_gateway_fee` double NOT NULL DEFAULT '0',
-`seller_shipping_fee` double NOT NULL DEFAULT '0',
-`seller_discount` double NOT NULL DEFAULT '0',
-`admin_commission` double NOT NULL DEFAULT '0',
-`admin_gateway_fee` double NOT NULL DEFAULT '0',
-`admin_shipping_fee` double NOT NULL DEFAULT '0',
-`admin_discount` double NOT NULL DEFAULT '0',
-`admin_subsidy` double NOT NULL DEFAULT '0',
+`seller_earning` decimal(19,4) NOT NULL DEFAULT '0',
+`seller_gateway_fee` decimal(19,4) NOT NULL DEFAULT '0',
+`seller_shipping_fee` decimal(19,4) NOT NULL DEFAULT '0',
+`seller_discount` decimal(19,4) NOT NULL DEFAULT '0',
+`admin_commission` decimal(19,4) NOT NULL DEFAULT '0',
+`admin_gateway_fee` decimal(19,4) NOT NULL DEFAULT '0',
+`admin_shipping_fee` decimal(19,4) NOT NULL DEFAULT '0',
+`admin_discount` decimal(19,4) NOT NULL DEFAULT '0',
+`admin_subsidy` decimal(19,4) NOT NULL DEFAULT '0',
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
`seller_earning` double NOT NULL DEFAULT '0',
`seller_gateway_fee` double NOT NULL DEFAULT '0',
`seller_shipping_fee` double NOT NULL DEFAULT '0',
`seller_discount` double NOT NULL DEFAULT '0',
`admin_commission` double NOT NULL DEFAULT '0',
`admin_gateway_fee` double NOT NULL DEFAULT '0',
`admin_shipping_fee` double NOT NULL DEFAULT '0',
`admin_discount` double NOT NULL DEFAULT '0',
`admin_subsidy` double NOT NULL DEFAULT '0',
`seller_earning` decimal(19,4) NOT NULL DEFAULT '0',
`seller_gateway_fee` decimal(19,4) NOT NULL DEFAULT '0',
`seller_shipping_fee` decimal(19,4) NOT NULL DEFAULT '0',
`seller_discount` decimal(19,4) NOT NULL DEFAULT '0',
`admin_commission` decimal(19,4) NOT NULL DEFAULT '0',
`admin_gateway_fee` decimal(19,4) NOT NULL DEFAULT '0',
`admin_shipping_fee` decimal(19,4) NOT NULL DEFAULT '0',
`admin_discount` decimal(19,4) NOT NULL DEFAULT '0',
`admin_subsidy` decimal(19,4) NOT NULL DEFAULT '0',

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (2)
includes/Upgrade/Upgrades/V_3_13_0.php (1)

10-16: Add method documentation for clarity.

While the code style is good, adding documentation would improve readability and maintainability. Consider adding a PHPDoc block to explain the purpose of the method, any parameters it might accept in the future, and what it returns.

Here's a suggested documentation block:

/**
 * Resyncs WooCommerce order stats to synchronize Dokan stats.
 *
 * This method performs two main actions:
 * 1. Creates a Dokan order stats table.
 * 2. Synchronizes WooCommerce order statistics.
 *
 * @since 3.13.0
 *
 * @return void
 */
public static function resync_wc_order_stats_to_sync_dokan_stats() {
    // ... (existing code)
}
includes/Upgrade/Manager.php (1)

35-35: Improved boolean conversion using explicit cast

The change from ! ! to (bool) is a good improvement. It makes the intention clearer and is more aligned with modern PHP coding practices. This modification enhances code readability without altering the function's behavior.

Consider adding a brief comment explaining why we're casting to boolean here, e.g.:

// Ensure a boolean return value regardless of what get_option() returns
return (bool) get_option( $this->is_upgrading_db_key, false );
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 0d84346 and 67443f3.

📒 Files selected for processing (3)
  • includes/Upgrade/Manager.php (1 hunks)
  • includes/Upgrade/Upgrades.php (1 hunks)
  • includes/Upgrade/Upgrades/V_3_13_0.php (1 hunks)
🔇 Additional comments (3)
includes/Upgrade/Upgrades/V_3_13_0.php (2)

1-8: LGTM: File structure and namespace are well-defined.

The file structure, namespace definition, and use statements are correctly implemented, adhering to PSR-4 autoloading standards.


9-9: Class definition looks good. Verify naming convention.

The class V_3_13_0 is correctly defined and extends DokanUpgrader. The naming convention seems to follow a version number format, which is likely used for upgrade scripts.

To ensure consistency, let's verify if this naming convention is used for other upgrade classes:

✅ Verification successful

Naming convention is consistent.

The class V_3_13_0 follows the established version number format for upgrade scripts, consistent with other classes in the includes/Upgrade/Upgrades directory.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for similar class naming patterns in the Upgrades directory

# Test: Search for class definitions in the Upgrades directory
rg --type php -g 'V_*.php' -g '!V_3_13_0.php' --no-filename -N '^class V_\d+_\d+_\d+ extends DokanUpgrader' includes/Upgrade/Upgrades

Length of output: 1209

includes/Upgrade/Upgrades.php (1)

46-46: LGTM! Verify the existence of the V_3_13_0 class.

The new entry for version 3.13.0 is correctly added and follows the established pattern. This change will enable the upgrade process for users updating to version 3.13.0 of the Dokan Lite plugin.

To ensure the upgrade process will work as expected, please verify that the V_3_13_0 class exists:

✅ Verification successful

Verification Successful: V_3_13_0 class exists and is properly implemented.

The V_3_13_0 class has been successfully located in includes/Upgrade/Upgrades/V_3_13_0.php and contains the necessary implementation to handle the upgrade process for version 3.13.0. No issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of the V_3_13_0 class file

# Test: Check if the V_3_13_0.php file exists in the expected directory
fd -t f "V_3_13_0.php" includes/Upgrade/Upgrades

# If the file exists, display its content for further verification
if [ $? -eq 0 ]; then
    echo "File found. Displaying content:"
    cat $(fd -t f "V_3_13_0.php" includes/Upgrade/Upgrades)
else
    echo "Error: V_3_13_0.php file not found in the expected directory."
fi

Length of output: 774

Comment on lines +10 to +16
public static function resync_wc_order_stats_to_sync_dokan_stats() {
// Create Dokan order stats table.
( new Installer() )->create_dokan_order_stats_table();

// Sync the WC order stats.
$import = ReportsSync::regenerate_report_data( null, false );
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider error handling, performance, and transactional integrity.

The resync_wc_order_stats_to_sync_dokan_stats method implementation is straightforward, but there are a few areas for improvement:

  1. Error Handling: Add try-catch blocks to handle potential exceptions and log errors.
  2. Performance: For large databases, this operation could be time-consuming. Consider adding a way to process this in batches or as a background job.
  3. Transactional Integrity: Wrap the operations in a database transaction to ensure atomicity.

Here's a suggested refactor to address these concerns:

public static function resync_wc_order_stats_to_sync_dokan_stats() {
    global $wpdb;

    try {
        $wpdb->query('START TRANSACTION');

        // Create Dokan order stats table.
        (new Installer())->create_dokan_order_stats_table();

        // Sync the WC order stats.
        $import = ReportsSync::regenerate_report_data(null, false);

        $wpdb->query('COMMIT');

        error_log('Successfully resynced WC order stats to Dokan stats.');
    } catch (\Exception $e) {
        $wpdb->query('ROLLBACK');
        error_log('Failed to resync WC order stats to Dokan stats: ' . $e->getMessage());
    }
}

Additionally, consider implementing a batching mechanism or background processing for better performance with large datasets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs: Testing This requires further testing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant