0 comments on “Directions 404 Error : marketing_at_am*(902.900)”

Directions 404 Error : marketing_at_am*(902.900)

Issue reported by customer: marketing_at_am*(902.900)

Add locations & generate embed.
In the resulting locations the Directions link is wrong.

Example: https://maps.googleapis.com/maps?saddr=Atlanta%20GA&daddr=1200%20Northside%20Forsyth%20Drive%2C%20Cumming%2C%20GA%2C%2030041%2C%20United%20States

0 comments on “New Manage Customers : Location Count Wrong”

New Manage Customers : Location Count Wrong

GitHub Project Issue: New Manage Customers : Location Count Wrong
Follow on to this task: Sysadmin : Manage Customers UX Improvement

Reproduction

The list of customers shows locations 0 for multiple customers with locations.

  • ID: 903.901 enterprise@st…
    Locations: 0
    Actual Locations: 25

Research

New Manage Customers Module (March 2026)

React manage_customers.tsx

File: WordPress/wp-content/plugins/myslp-dashboard/src/manage_customers/manage_customers.tsx

DataGridPro (from MUIx framework) properties…

— Data set

Most likely from

    React.useEffect( () => {
        fetchData();
    }, [ fetchData ] );

Calls REST endpoint from 
const restBase: string = slpReact.url.rest + 'myslp/v2/customers';

— Column definitions

const columns = React.useMemo( () => buildColumns( homeUrl, isMonthEnd ), [ homeUrl, isMonthEnd ] );
  • function buildColumns
    • const cols: GridColDef[]…
      • field: location_count

homeUrl most likely comes from the PHP class \MySLP_Manage_Customers::extendReactVars
set to WordPress get_home_url()

REST Backend

SaaS App backend via MySLP Dashboard plugin.

— Fetching Customers
PHP method \MySLP_REST_API::register_routes defines the registered routes for WordPress.
register_rest_route( $this->myslp_namespace, ‘/customers’,…)
Calls the PHP method \MySLP_REST_API::get_customers

Location count is coming from $this->myslp->User->location_count

Root Cause Theory

This appears to be using a meta_query to fetch the user location data.
This is NOT accurate.

In some cases the MySLP_User object does not have a location_count user_meta property set.
If that is the case, it should call \SLP_Location_Manager::get_location_count for that user and store the result with

User Location Count Architecture

\MySLP_User::__get

Fetched from user_meta with the location_count property.
This is likely where the AI decided to make this a source of truth for location counts.

				case 'location_count':
				case 'mapview_count':
					$this->__get( 'user_meta' );
					$this->$property = (int) ( $this->user_meta[ $property ][0] ?? 0 );
					break;

\MySLP_REST_API::get_location_count_for_user

Currently unused anywhere in the project.
This would ensure the app switched to the user’s blog and set_database_meta() then called:
\SLP_Location_Manager::get_location_count

\SLP_Location_Manager::get_location_count

This is the original method from the legacy app code to fetch location counts.
It queries the custom SLP database that is added for every user to get the count of records.
It comes from the linchpin Store Locator Plus base plugin.

				$the_count            = $this->slplus->database->get_Value( array(
					'selectall_count',
					'where_default'
				) );


Resolution

Update \MySLP_REST_API::get_customers must first call…

// Update count and user meta storing count.
$this->get_location_count_for_user( $user->ID );

This updates the myslp->User->location_count meta by querying the SLP custom table directly.

See myslp-dashboard git repo update SHA 4f54ff1154d0cf148c603000bdcd789a669ed8cc

0 comments on “Sysadmin : Manage Customers UX Improvement”

Sysadmin : Manage Customers UX Improvement

With the SaaS dashboard there is a Manage | Customers option that displays the customer list. It is using a default WordPress table style presentation that has been modified by one of the SaaS plugins, most likely MySLP Dashboard (myslp-dashboard). I would like to make improvements to this interface.

0 comments on “Cancelling Subscription Creates New Subscription”

Cancelling Subscription Creates New Subscription

I had to update the stripe connection which meant rewriting how subscription processing is managed including cancellations.

So for the customer mcampbell_at_tnwebtech_dot_com (830.828) this is what I have as the status:
original subscription 24th
last renewed feb 24th
cancelled mar 6th
stripe charged them mar 6th AND marked it cancelled april 6th
it should have marked the 24th subscription to cancel on mar 24th

Clearly a bug in the new cancellation processor.

Task: https://github.com/Store-Locator-Plus/myslp_aws_ecs_kit/issues/94


Dev Notes

Customer: mc…tnwebtech… (830.828)

customer: mcampbell@tnwebtech.com

Current status according to Stripe: they have set their account to cancel on April 5th
Current subscription: *z8ku is deleted on Stripe now meaning it will not auto-renew

Please ensure that is what they want.

From the Stripe history:
The original subscription *9h4z
Started Oct 24 2023
Cancelled via SLP Dashboard on Mar 6th 2026 at 1:05AM (server time)
Was set to stop providing SLP maps on Mar 24th 2026
They then renewed (created the new subscription) Mar 6th at 1:08AM (server time)
This is set to expire on April 5th 2026

Yes, we have an issue with RENEW
If the prior subscription is still active (*9h4z in this case) it should set the new subscription (renewal) to start when that ends (Mar 24th 2026 06:21AM server time)
The bug is that is started immediately , thus the new 6th to 5th dates
That is OK for renewals that happen AFTER the maps are disabled (most users) but in this unique situation it needs to be addressed.

Stripe


Current Subscription *z8ku

Started and cancelled March 6th 2026

Mar 6, 2026, 1:08:53 AM EDT POST/v1/subscriptions

{
  "id": "sub_1T7rZBBvHKfBw2LGODU6z8ku",
  "object": "subscription",
...
  "cancel_at": null,
  "cancel_at_period_end": false,
  "canceled_at": null,
  "cancellation_details": {
    "comment": null,
    "feedback": null,
    "reason": null,
   },
  "collection_method": "charge_automatically",
  "created": 1772777333,
  "currency": "usd",
  "current_period_end": 1775455733, // April 5 2026 06:22:13
  "current_period_start": 1772777333,
  "customer": "cus_OsOnxeaYjgqPNu",
...
  "items": {
    "object": "list",
    "data": [
      {
        "id": "si_U63gr60piiTUmH",
        "object": "subscription_item",
        "billing_thresholds": null,
        "created": 1772777334,
        "current_period_end": 1775455733,
        "current_period_start": 1772777333,
        "discounts": [],
        "metadata": {},
        "plan": {
          "id": "Professional",
          "object": "plan",
          "active": true,
          "aggregate_usage": null,
          "amount": 3500,
          "amount_decimal": "3500",
          "billing_scheme": "per_unit",
          "created": 1500935159,
          "currency": "usd",
          "interval": "month",
          "interval_count": 1,
          "livemode": true,
          "metadata": {},
          "meter": null,
          "nickname": null,
          "product": "prod_BU6KhAFcwnXTef",
          "tiers_mode": null,
          "transform_usage": null,
          "trial_period_days": null,
          "usage_type": "licensed"
        },
        "price": {
          "id": "Professional",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1500935159,
          "currency": "usd",
          "custom_unit_amount": null,
          "livemode": true,
          "lookup_key": null,
          "metadata": {},
          "nickname": null,
          "product": "prod_BU6KhAFcwnXTef",
          "recurring": {
            "aggregate_usage": null,
            "interval": "month",
            "interval_count": 1,
            "meter": null,
            "trial_period_days": null,
            "usage_type": "licensed"
          },
          "tax_behavior": "unspecified",
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "recurring",
          "unit_amount": 3500,
          "unit_amount_decimal": "3500"
        },
        "quantity": 1,
        "subscription": "sub_1T7rZBBvHKfBw2LGODU6z8ku",
        "tax_rates": []
      }
    ],
...
  },
...
  "trial_settings": {
    "end_behavior": {
      "missing_payment_method": "create_invoice"
    }
  },
  "trial_start": null
}

Mar 6, 2026, 1:09:11 AM EDT POST /v1/subscriptions/sub_1T7rZBBvHKfBw2LGODU6z8ku

{
  "id": "sub_1T7rZBBvHKfBw2LGODU6z8ku",
  "object": "subscription",
...
  "cancel_at": 1775455733,
  "cancel_at_period_end": true,
  "canceled_at": 1772777351,
  "cancellation_details": {
    "comment": null,
    "feedback": null,
    "reason": "cancellation_requested"
  },
  "collection_method": "charge_automatically",
  "created": 1772777333,
  "currency": "usd",
  "current_period_end": 1775455733,
  "current_period_start": 1772777333,
  "customer": "cus_OsOnxeaYjgqPNu",
...
}

Mar 6, 2026, 1:09:12 AM EDT DELETE/v1/subscriptions/sub_1T7rZBBvHKfBw2LGODU6z8ku


Original Subscription: *h4z

Started: 2023-10-24
Ended: 2026-03-06 01:05AM

Mar 6, 2026, 1:05:04 AM EDT POST/v1/subscriptions/sub_1O4dzSBvHKfBw2LGsKZp9h4z

{
  "id": "sub_1O4dzSBvHKfBw2LGsKZp9h4z",
  "object": "subscription",
  "application": null,
  "application_fee_percent": null,
  "automatic_tax": {
    "disabled_reason": null,
    "enabled": false,
    "liability": null
  },
  "billing_cycle_anchor": 1698128482,
  "billing_cycle_anchor_config": null,
  "billing_mode": {
    "flexible": null,
    "type": "classic"
  },
  "billing_thresholds": null,
  "cancel_at": 1774333282, // Mar 24 2026 06:21:22 AM (correct)
  "cancel_at_period_end": true,
  "canceled_at": 1772777104, // Mar 6 2026 01:05:04 AM
  "cancellation_details": {
    "comment": null,
    "feedback": null,
    "reason": "cancellation_requested"
  },
  "collection_method": "charge_automatically",
  "created": 1698128482,
  "currency": "usd",
  "current_period_end": 1774333282, // Mar 24 2026 06:21:22 AM (correct)
  "current_period_start": 1771914082, // February 23 2026 11:21:22 PM
  "customer": "cus_OsOnxeaYjgqPNu",
  "customer_account": null,
  "days_until_due": null,
  "default_payment_method": null,
  "default_source": null,
  "default_tax_rates": [],
  "description": null,
  "discount": null,
  "discounts": [],
  "ended_at": null,
  "invoice_settings": {
    "account_tax_ids": null,
    "issuer": {
      "type": "self"
    }
  },
  "items": {
    "object": "list",
    "data": [
      {
        "id": "si_OsOnhVkp9iBCCb",
        "object": "subscription_item",
        "billing_thresholds": null,
        "created": 1698128483,
        "current_period_end": 1774333282,
        "current_period_start": 1771914082,
        "discounts": [],
        "metadata": {},
        "plan": {
          "id": "Professional",
          "object": "plan",
          "active": true,
          "aggregate_usage": null,
          "amount": 3500,
          "amount_decimal": "3500",
          "billing_scheme": "per_unit",
          "created": 1500935159,
          "currency": "usd",
          "interval": "month",
          "interval_count": 1,
          "livemode": true,
          "metadata": {},
          "meter": null,
          "nickname": null,
          "product": "prod_BU6KhAFcwnXTef",
          "tiers_mode": null,
          "transform_usage": null,
          "trial_period_days": null,
          "usage_type": "licensed"
        },
        "price": {
          "id": "Professional",
          "object": "price",
          "active": true,
          "billing_scheme": "per_unit",
          "created": 1500935159,
          "currency": "usd",
          "custom_unit_amount": null,
          "livemode": true,
          "lookup_key": null,
          "metadata": {},
          "nickname": null,
          "product": "prod_BU6KhAFcwnXTef",
          "recurring": {
            "aggregate_usage": null,
            "interval": "month",
            "interval_count": 1,
            "meter": null,
            "trial_period_days": null,
            "usage_type": "licensed"
          },
          "tax_behavior": "unspecified",
          "tiers_mode": null,
          "transform_quantity": null,
          "type": "recurring",
          "unit_amount": 3500,
          "unit_amount_decimal": "3500"
        },
        "quantity": 1,
        "subscription": "sub_1O4dzSBvHKfBw2LGsKZp9h4z",
        "tax_rates": []
      }
    ],
    "has_more": false,
    "total_count": 1,
    "url": "/v1/subscription_items?subscription=sub_1O4dzSBvHKfBw2LGsKZp9h4z"
  },
  "latest_invoice": "in_1T4EzzBvHKfBw2LGXjuYItOu",
  "livemode": true,
  "metadata": {},
  "next_pending_invoice_item_invoice": null,
  "on_behalf_of": null,
  "pause_collection": null,
  "payment_settings": {
    "payment_method_options": null,
    "payment_method_types": null,
    "save_default_payment_method": null
  },
  "pending_invoice_item_interval": null,
  "pending_setup_intent": null,
  "pending_update": null,
  "plan": {
    "id": "Professional",
    "object": "plan",
    "active": true,
    "aggregate_usage": null,
    "amount": 3500,
    "amount_decimal": "3500",
    "billing_scheme": "per_unit",
    "created": 1500935159,
    "currency": "usd",
    "interval": "month",
    "interval_count": 1,
    "livemode": true,
    "metadata": {},
    "meter": null,
    "nickname": null,
    "product": "prod_BU6KhAFcwnXTef",
    "tiers_mode": null,
    "transform_usage": null,
    "trial_period_days": null,
    "usage_type": "licensed"
  },
  "quantity": 1,
  "schedule": null,
  "start_date": 1698128482,
  "status": "active",
  "test_clock": null,
  "transfer_data": null,
  "trial_end": null,
  "trial_settings": {
    "end_behavior": {
      "missing_payment_method": "create_invoice"
    }
  },
  "trial_start": null
}

Mar 6, 2026, 1:05:05 AM EDT DELETE/v1/subscriptions/sub_1O4dzSBvHKfBw2LGsKZp9h4z


SLP SaaS

Currently on Professional Plan
Expires 2026-05-21 06:08:53
Cancelled 2026-03-06 06:09:11

Current Stripe subscription: sub_1T7rZBBvHKfBw2LGODU6z8ku


Stripe Notes

Billing mode

Currently using Classic billing mode.

Flexible Recommended: Provides accurate and predictable billing behavior and new capabilities. To access these improvements, which are only available in flexible billing mode, you must create new subscriptions with flexible billing mode or migrate your existing subscriptions.

*Classic: Uses the existing Stripe subscription behavior. This setting is maintained for backward compatibility with older integrations.

AI Resolution Assistance

Prompt

@Amelia -
In the MySLP Payments module (WordPress/wp-content/plugins/myslp-payments) there is an issue related to renewing cancelled subscriptions.

__
Make a note of this as general knowledge about the Store Locator Plus Saas Application:
- local (https://local.storelocatorplus.com) and staging (https://staging.storelocatorplus.com) servers may be using outdated data sets
- local and staging servers employ the Stripe TEST environment and related keys 
- the production server uses live keys
- NEVER run tests against live Stripe customer data using live keys even on the staging or local servers

__

The following scenario is a real-world situation which played out on the production version of the SaaS application.   

We have an issue with RENEW subscription.
- If the prior subscription is still active (sub_1O4dzSBvHKfBw2LGsKZp9h4z in this case) it should set the new subscription (sub_1T7rZBBvHKfBw2LGODU6z8ku) to start when the still-active subscription ends (Mar 24th 2026 06:21AM server time).
- The bug is that the new subscription started immediately setting a March 6th start date when an April 5th end date.
- The new subscription should have started on March 24th 2026 at 6:21AM.
- If the  prior subscription is past the end (cancel_at) date, only then should the renewal start immediately.  That was not the case in this situation.


Meta data about the customer and their interaction with the application:

customer: mcampbell@tnwebtech.com

Current status according to Stripe: they have set their account to cancel on April 5th
Current subscription: *z8ku is deleted on Stripe now meaning it will not auto-renew

Please ensure that is what they want.

From the Stripe history:
The original subscription *9h4z
Started Oct 24 2023
Cancelled via SLP Dashboard on Mar 6th 2026 at 1:05AM (server time)
Was set to stop providing SLP maps on Mar 24th 2026
They then renewed (created the new subscription) Mar 6th at 1:08AM (server time)
This is set to expire on April 5th 2026

AI Fix

in \stripe\MySLP_Stripe_Payments::renew_subscription add the trial_end argument.


		// If the old subscription still has remaining paid time, defer the new
		// subscription so it starts when the old period ends.
		$prior_period_end = $this->subscription->current_period_end ?? null;
		if ( $prior_period_end && $prior_period_end > time() ) {
			$args['trial_end'] = $prior_period_end;
		}

		try {
			$this->subscription    = Subscription::create( $args );

E2E Testing

Write a new E2E Test Specification "subscription_renewals".

The first test in the specification needs to test "Can renew a subscription before it has expired".
This is a corner case with some specific requirements.
- Login as a user with a current active subscription
- Go to My Profile and look for the current subscription ID, remember this value
- Go to My Profile and cancel the subscription
-- The current Stripe subscription ID should be posted and marked in Stripe as canceled
-- The current subscription should have a cancellation date at the end of the current period
- Go to My Profile and renew the subscription
-- This should create a new Stripe subscription ID
-- The new Stripe subscription ID should start when the current period ends
-- The new Stripe subscription should NOT start at the date/time of the renewal
-- The new Stripe subscription should be set to renew in a month (current period ends a month later)



0 comments on “Update SLP_Country_Manager To Include All Regions”

Update SLP_Country_Manager To Include All Regions

Contains the map and other data that drives SLP for each country.
ccTLD is the region parameter for Google Maps
ccTLD is any of the Unicode region subtag identifiers

See https://developers.google.com/maps/coverage for a list of supported regions, 2D/3D map tiles apply here

\SLP_Country_Manager::load_country_data sets up the list of country meta data for this purpose.
It has not been updated since 2018.

0 comments on “SLP Did Not Initialize On White Black Classic Theme”

SLP Did Not Initialize On White Black Classic Theme

The main locator page with the [slplus] shortcode generates the same message:

“Store Locator Plus® did not initialize properly.”

Reproduction

  • Login as admin
  • Download and Activate the White Black Classic theme by Masino1967
  • Activate the SLP base plugin
  • Add a page and put the [slplus] shortcode on the page
0 comments on “WPSLP Widget Enqueue Script Problem”

WPSLP Widget Enqueue Script Problem

This issue is specific to the WordPress plugin stack and does not affect SaaS installations.

Widget areas are special places on a classic theme that can accept blocks — typically areas like your sidebar or footer. This guide will explain how to use widgets on your website.

Sites using modern block themes do not use widgets, so you won’t find Appearance → Widgets in your dashboard.

Without a theme that supports widgets, the only place you’ll get Appearance -> Widgets support is with the Power add on for the Store Pages “no store page” template. The “no store page” template has not been updated to use blocks instead of widgets.

0 comments on “\SLPlus::enqueue_google_maps_script – slp_core dependency is not loaded for Admin pages”

\SLPlus::enqueue_google_maps_script – slp_core dependency is not loaded for Admin pages

Notice: Function WP_Scripts::add was called incorrectly. The script with the handle “google_maps” was enqueued with dependencies that are not registered: slp_core. Please see Debugging in WordPressfor more information. (This message was added in version 6.9.1.) in /var/www/html/wp-includes/functions.php on line 6131

\SLPlus::enqueue_google_maps_script calls enqueue scripts with slp_core as a dependency but it is missing when going to the Store Locator Plus | Locations page in the admin panel.