[ADMIN] How to import help content via SJ FAQs

  1. Network Admin (main site) → SJ FAQs → Export/Import.
  2. Click Import, choose the JSON file (e.g. sj-faqs-enduser-import.json).
  3. Review the dry-run summary — counts of new vs. updated entries.
  4. Click Run Import.
  5. If the JSON has shh blocks, sj-help-hub auto-stamps screen context and admin visibility on each entry.
  6. Network Admin → SJ Help Hub → Flush all caches to push entries to every subsite Help menu.
  7. Spot-check one subsite: Help menu shows the new entries, the contextual Help tab on each CRM screen shows the right ones.

[ADMIN] Brand and contact info reference

For all customer-facing copy, legal pages, invoices, and email signatures:

  • Company: SJ Notebook
  • Address: Braintree, MA, USA
  • Support email: support@sjnotebook.com
  • App domain: sjcrmapp.com
  • Marketing domain: sjnotebook.com

Do not put a personal email or street address in customer-facing copy.

[ADMIN] Database table prefix and key tables

Table prefix: wpp3_

Key custom tables:

  • wpp3_sj_crm_tenants — tenant registry (blog_id ↔ stripe_customer_id ↔ plan)
  • wpp3_sj_journal_entries — work log
  • wpp3_ai_task_manager_tasks — pending tasks/ideas
  • wpp3_sj_changelog_entries — release changelog
  • wpp3_sj_sections — section ID registry (sj-sec-XXX)

Subsite-scoped tables use prefix wpp3_{blog_id}_ per WP multisite convention.

[ADMIN] Master copies of plugins — where to edit

Always edit the master copy. Listed in project-hub/.../project-hub-manager/data/projects-map.json.

SJ CRM plugins live at: C:UsersWin11pcLocal Sitessj-crm-40apppublicwp-contentplugins

  • sj-crm — main CRM plugin (HOLD — do not modify)
  • sj-crm-stripe — billing
  • sj-crm-signup — multi-tenant signup
  • sj-crm-health, sj-crm-items, sj-crm-rentals, sj-crm-projects — modules
  • sj-faqs, sj-help-hub — help system

Never edit files on the live server directly — changes get overwritten on next deploy.

[ADMIN] Where are tenant subsites provisioned?

Tenant subsites are auto-created by sj-crm-stripe on successful checkout via the checkout.session.completed webhook.

Flow: Stripe Checkout → webhook fires → SJ_CRM_Stripe_Tenant_Provisioner::create_tenant_site()wpmu_create_blog() with slug from form → sj-crm plugins activated on the new blog → admin user assigned.

Subsites live at sjcrmapp.com/{slug}/. The blog_id and stripe_customer_id are stored together in wpp3_sj_crm_tenants.

[ADMIN] How to deploy a plugin update to production

  1. Bump version in plugin header AND in the VERSION constant. Both must match.
  2. Update projects-map.json with new version.
  3. Add changelog entry to plugin’s readme.txt or CHANGELOG.md.
  4. Run a manual DB backup (Network Admin → Tools or hosting panel).
  5. Zip the plugin folder — user does this, not the agent.
  6. Upload via SFTP or Network Admin → Plugins → Upload.
  7. Network Activate (or activate per-site if it’s a single-tenant module).
  8. Smoke-test on one subsite: load each main screen, save one record.
  9. Purge LiteSpeed Cache: LiteSpeed Cache → Toolbox → Purge All.
  10. Log in SJ Journal: what changed, version bumped, any issues.

[ADMIN] What Stripe webhook events are handled?

Six events, all in sj-crm-stripe/sj-crm-stripe.phphandle_webhook():

  • checkout.session.completed — provisions tenant site
  • invoice.paid — extends subscription period
  • invoice.payment_failed — sends dunning email, flags account
  • customer.subscription.updated — syncs plan changes
  • customer.subscription.deleted — deactivates tenant (does not delete data)
  • checkout.session.expired — cleans up unfinished signups

Webhook signing secret is in wp_options → sj_crm_stripe_webhook_secret.

[ADMIN] How to manually provision a tenant subsite

Use only if Stripe webhook fails or for comped accounts.

  1. Network Admin → Sites → Add New.
  2. Site Address: customer’s chosen slug.
  3. Site Title: business name.
  4. Admin Email: customer’s email.
  5. Save.
  6. Edit the new site → Plugins tab → activate sj-crm and any modules they paid for.
  7. Add row to wpp3_sj_crm_tenants with the new blog_id and Stripe customer ID (if any).
  8. Email the customer their login link.

For comped accounts, still create a Stripe customer (no card) so future upgrades work cleanly.

[ADMIN] What’s the difference between cancelling and deactivating a tenant?

Cancelled = subscription ended, but the subsite still exists and data is retained for 30 days. User can resubscribe to reactivate.

Deactivated = tenant flag set, login blocked at the subsite, but database rows still present. Triggered automatically by customer.subscription.deleted.

Deleted = manual super-admin action. Run after the 30-day grace period for non-resubscribed accounts. Use Network Admin → Sites → Delete.

Never delete a tenant without confirming the customer is past the grace period and has been emailed.

[ADMIN] How to investigate a failed Stripe webhook

  1. Stripe Dashboard → Developers → Webhooks → pick the endpoint.
  2. Find the failed delivery (status Failed or Pending retry).
  3. View the response body — look for PHP error or non-200 status.
  4. Cross-reference with wp-content/debug.log at the same timestamp.
  5. Common causes: signing secret mismatch, plugin deactivated, fatal error in webhook handler, 502 from server.
  6. Once fixed, click Resend in Stripe to replay the event.
  7. Verify the side effect ran (tenant created, subscription extended, etc.).