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

CRM: Fix dashboard contact graph #38316

Merged
merged 5 commits into from
Nov 1, 2024

Conversation

gogdzl
Copy link
Contributor

@gogdzl gogdzl commented Jul 12, 2024

Fixes https://github.com/Automattic/zero-bs-crm/issues/3468

Proposed changes:

  • This PR fixes the dashboard contact graph which shows wrong values in some instances.

Other information:

  • Have you written new tests for your changes, if applicable?
  • Have you checked the E2E test CI results, and verified that your changes do not break them?
  • Have you tested your changes on WordPress.com, if applicable (if so, you'll see a generated comment below with a script to run)?

Jetpack product discussion

https://github.com/Automattic/zero-bs-crm/issues/3468

Does this pull request change what data or activity we track or use?

No.

Testing instructions:

  • Create one contact in the last day of the month
  • Change your timezone to a high enough value that would cause the day to overflow, when changing timezones
  • Verify that the graph gets shifted
  • Apply this PR's code to your CRM installation
  • Verify that the error is gone

Alternatively just test the new code and check if the behavior is consistently the same as the previous, and that the new code looks good enough.

@gogdzl gogdzl added [Type] Bug When a feature is broken and / or not performing as intended [Plugin] CRM Issues about the Jetpack CRM plugin labels Jul 12, 2024
@gogdzl gogdzl requested a review from tbradsha July 12, 2024 03:09
@gogdzl gogdzl self-assigned this Jul 12, 2024
@gogdzl gogdzl requested review from cleacos and coder-karen July 12, 2024 03:09
@github-actions github-actions bot added the Admin Page React-powered dashboard under the Jetpack menu label Jul 12, 2024
Copy link
Contributor

github-actions bot commented Jul 12, 2024

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • 🔴 Add a "[Status]" label (In Progress, Needs Team Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


The e2e test report can be found here. Please note that it can take a few minutes after the e2e tests checks are complete for the report to be available.


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Choose a review path based on your changes:
    • A. Team Review: add the "[Status] Needs Team Review" label
      • For most changes, including minor cross-team impacts.
      • Example: Updating a team-specific component or a small change to a shared library.
    • B. Crew Review: add the "[Status] Needs Review" label
      • For significant changes to core functionality.
      • Example: Major updates to a shared library or complex features.
    • C. Both: Start with Team, then request Crew
      • For complex changes or when you need extra confidence.
      • Example: Refactor affecting multiple systems.
  3. Get at least one approval before merging.

Still unsure? Reach out in #jetpack-developers for guidance!

@github-actions github-actions bot added the [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! label Jul 12, 2024
Copy link
Contributor

@coder-karen coder-karen left a comment

Choose a reason for hiding this comment

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

Nice, thanks for working on this.

What would be the best way to change the timezone? In my case I created a contact and set the creation date for June 30th UTC+0, evening. Changed my timezone in WordPress to UTC+13 which changed the contact creation date to July 1st. The dashboard graph still shows the contact entry for June, both with and without the PR.

@gogdzl gogdzl added [Status] Needs Review To request a review from fellow Jetpack developers. Label will be renamed soon. and removed [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! Admin Page React-powered dashboard under the Jetpack menu labels Jul 15, 2024
@github-actions github-actions bot added the Admin Page React-powered dashboard under the Jetpack menu label Jul 15, 2024
@gogdzl
Copy link
Contributor Author

gogdzl commented Jul 15, 2024

What would be the best way to change the timezone? In my case I created a contact and set the creation date for June 30th UTC+0, evening. Changed my timezone in WordPress to UTC+13 which changed the contact creation date to July 1st. The dashboard graph still shows the contact entry for June, both with and without the PR.

That's a great question. That should've bugged the dashboard's graph. Adjust inside your database zbsc_created so MONTH(FROM_UNIXTIME(zbsc_created)) as month returns June on your machine's timezone.

@gogdzl gogdzl requested a review from coder-karen July 15, 2024 13:49
@coder-karen
Copy link
Contributor

Yes that's how I adjusted the zbsc_created initially for the contact, the timestamp there (in the database, for zbsc_created) is for June 30th, unless I'm misunderstanding 🤔

Copy link
Contributor

@cleacos cleacos left a comment

Choose a reason for hiding this comment

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

To test this way:

We could use the WP installation timezone configured:

$datetime_month = new DateTime( '@', $v->ts );
$datetime_month->setTimezone( new DateTimeZone('the_UTC_time_zone') );
$the_month = $datetime_month->format( 'M y' );

@coder-karen
Copy link
Contributor

We could use the WP installation timezone configured:

@cleacos Do you mean the existing code could be replaced by the suggested code there? Not sure I'm following on that, but I tried doing so using the 'Europe/London' DateTimeZone, and encountered an issue because of the '@' - uncaught Exception: Failed to parse time string (@) at position 0 (@):. Removing that, I'm also encountering Undefined property: stdClass::$ts, as ts isn't a property on $v.
So again I'm probably misunderstanding what the intention is here :)

@coder-karen coder-karen added [Status] Needs Team Review and removed [Status] Needs Review To request a review from fellow Jetpack developers. Label will be renamed soon. labels Aug 22, 2024
@coder-karen coder-karen added [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! and removed [Status] Needs Team Review labels Sep 4, 2024
@coder-karen coder-karen removed their request for review October 7, 2024 10:05
@tbradsha
Copy link
Contributor

tbradsha commented Oct 8, 2024

👋 Indeed, this is a timezone-related bug! However, this PR wouldn't fix it.

  1. Removing the ts column from the SELECT: not a problem; it was probably an arbitrary column used to debug.
  2. While I haven't tested the other changes, I'm positive they don't address the core issue. By the time you're past the queries, the grouping and counts have already been pulled and no amount of shifting timezones or whatever will affect that.

There are a few ways to handle this. My recommendation is to NOT rely on gmdate or the raw DateTime object. There are several functions in includes/jpcrm-localisation.php that are timezone-friendly. In this case, you'll probably want jpcrm_get_wp_timezone_offset() (jpcrm_get_wp_timezone_offset_in_seconds() could be used too, but in this instance would result in much messier queries):

$tz_offset = jpcrm_get_wp_timezone_offset();

My preferred solution would be to set the MySQL timezone to jpcrm_get_wp_timezone_offset(). I'm not sure if that's a possibility with $wpdb. Note that in whatever solution you use, timezone codes (e.g. 'UTC') are not portable, but +5:00 should work consistently.

If there's not an easy way to adjust the timezone globally, you can try something like this:

$sql    = $wpdb->prepare( 'SET time_zone = "' . $tz_offset . '"; SELECT count(ID) as count, YEAR(FROM_UNIXTIME(zbsc_created)) as year FROM ' . $ZBSCRM_t['contacts'] . ' WHERE zbsc_created > %d AND zbsc_created < %d GROUP BY year ORDER BY year', $start_date, $end_date ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$yearly = $wpdb->get_results( $sql );

However, I'm not sure if $wpdb->prepare() allows multiple queries in this manner. If not, this would work well enough:

$sql    = $wpdb->prepare( 'SELECT count(ID) as count, YEAR(CONVERT_TZ(FROM_UNIXTIME(zbsc_created),"SYSTEM","' . $tz_offset . '")) as year FROM ' . $ZBSCRM_t['contacts'] . ' WHERE zbsc_created > %d AND zbsc_created < %d GROUP BY year ORDER BY year', $start_date, $end_date ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.VariableNotSnakeCase
$yearly = $wpdb->get_results( $sql );

Technically FROM_UNIXTIME() is lossy, but that shouldn't matter in this case.


For testing, I'd recommend using a creation date of 1830297600 (1 January 2028, 0:00:00 UTC) and 1830301200 (1 January 2028, 1:00:00 UTC). This'll make it easy to switch the WP timezone from -1:00 to 0:00 to +1:00 and spot the chart change in year and month.


As an aside, there might be another place that is affected in the same way:

$sql = $wpdb->prepare( 'SELECT SUM(' . $column_prefix . 'total) as total, MONTH(FROM_UNIXTIME(' . $column_prefix . 'date)) as month, YEAR(FROM_UNIXTIME(' . $column_prefix . 'date)) as year FROM ' . $ZBSCRM_t['transactions'] . ' WHERE ' . $column_prefix . 'date > %d AND ' . $column_prefix . 'date < %d' . $transStatusQueryAdd . ' GROUP BY month, year ORDER BY year, month', $paidAfter, $paidBefore );

@tbradsha
Copy link
Contributor

tbradsha commented Oct 9, 2024

Per this comment in documentation, there may be an undocumented time_zone property on $wpdb:

https://developer.wordpress.org/reference/classes/wpdb/

@gogdzl gogdzl requested review from coder-karen and cleacos October 25, 2024 19:54
@gogdzl
Copy link
Contributor Author

gogdzl commented Oct 25, 2024

Per this comment in documentation, there may be an undocumented time_zone property on $wpdb:

https://developer.wordpress.org/reference/classes/wpdb/

Tried, didn't work.

@gogdzl
Copy link
Contributor Author

gogdzl commented Oct 25, 2024

If there's not an easy way to adjust the timezone globally, you can try something like this:

It works! Thanks, @tbradsha!

Copy link
Contributor

@coder-karen coder-karen left a comment

Choose a reason for hiding this comment

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

Thanks for the changes!

I tested again, and this time I got what I believe is the expected result (different to last time), but want to make sure that's expected:

  • I set the contact creation date to late in the day UTC+0 Sep 30th. The contact shows in September in the dashboard. I then change the site timezone to UTC+13 - the contact now shows in October in the dashboard.
  • Same results following the suggestion here - I changed the creation date to 1st Jan (but 2024, not 2028), 0:00:00 and 1:00:00 UTC. The dashboard continues to show the contact in Jan regardless of timezone change without the PR, and with the PR if the timezone change switches the creation date to the previous month the dashboard now reflects that.

@tbradsha
Copy link
Contributor

want to make sure that's expected

Based on your description, it sounds like it's doing what it should: showing the creation date based on the currently-selected WP timezone.

@@ -69,17 +69,20 @@ function jetpackcrm_dash_refresh() {
);
}

$tz_offset = esc_sql( (string) jpcrm_get_wp_timezone_offset() );
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a blocker, but the cast should be unnecessary, as wp_timezone_string() should always return a valid string, and everything else uses built-ins.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm escaping this because we are not calling wp_timezone_string directly.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, I was referring to the cast. :^)

Comment on lines +96 to +97
$datetime_month = DateTime::createFromFormat( '!m Y', $v->month . ' ' . $v->year );
$the_month = $datetime_month->format( 'M y' );
Copy link
Contributor

Choose a reason for hiding this comment

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

I still think the timestamp way is more readable than this way, though that'd require keeping that column in the database.

Copy link
Contributor

@tbradsha tbradsha left a comment

Choose a reason for hiding this comment

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

Seems to work.

@gogdzl gogdzl merged commit b0a775c into trunk Nov 1, 2024
54 checks passed
@gogdzl gogdzl deleted the fix/crm/3468-dashboard-contact-graph-fix branch November 1, 2024 04:16
@github-actions github-actions bot removed the [Status] Needs Author Reply We would need you to make some changes or provide some more details about your PR. Thank you! label Nov 1, 2024
@github-actions github-actions bot added this to the crm/6.4.4 milestone Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Admin Page React-powered dashboard under the Jetpack menu [Plugin] CRM Issues about the Jetpack CRM plugin [Type] Bug When a feature is broken and / or not performing as intended
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants