π Changelog
All updates and improvements to SimProSync
v1.9.3
11 Apr 2026
π‘οΈ Duplicate Creation Prevention & Multiple Webhook Fixes
Latest- β FIX #1: LOOP PREVENTION (v1.9.0 webhook)
- β Job status was flip-flopping (Pending β Progress) causing multiple notifications
- β Root cause: GHLβSimProβGHL echo loop when both sides fired webhooks
- β Now fetches current job/quote state BEFORE updating
- β Skips redundant updates if Stage/Status already match (logs show "π LOOP PREVENTED")
- β Also removed AutoAdjustStatus=false which was permanently disabling SimPro's Auto Adjust
- β
- β FIX #2: ENTITY TYPE ROUTING (v1.9.1 webhook)
- β Creating opportunity in "Ongoing Jobs Pipeline" was creating a Quote instead of Job
- β Root cause: ACTION code always called createSimproQuote() regardless of entity_type
- β Now checks entity_type from pipeline_stage_mappings and routes correctly
- β Added new createSimproJob() function for direct job creation from opportunities
- β Logs now show "β‘ ACTION: Creating Job for Opportunity..." when entity_type=job
- β
- β FIX #3: ARCHIVING BUG (v1.9.2 webhook)
- β Quotes/Jobs weren't archiving when moved to "Ghosted" or "Abandoned" stages
- β Root cause: archive_reason_id was extracted from mapping but never added to API payload
- β SimPro requires ArchiveReason array when Stage="Archived"
- β Now includes ArchiveReason in update payload (logs show "π Adding ArchiveReason ID X")
- β
- β FIX #4: DUPLICATE CREATION (v1.9.3 webhook)
- β Multiple GHL workflows firing simultaneously could create duplicate jobs/quotes
- β Root cause: No deduplication lock for job/quote creation (only sites had this)
- β Added lock-based deduplication using acquireCreationLock() pattern
- β First webhook creates entity; subsequent webhooks detect and skip
- β Logs show "π DEDUP: job #X already created for opportunity by another webhook"
- β
- β ENHANCEMENT: GOOGLE DRIVE FILE NAMING
- β Files uploaded to Google Drive now include customer name in filename
- β Original: "photo.jpg" β New: "photo - John Smith.jpg"
- β Makes it easier to identify files in Drive without opening folders
- β Customer name is sanitized to remove invalid filename characters
v1.9.0
6 Apr 2026
ποΈ Deletion Manager
- β NEW FEATURE: Admin-only Deletion Manager for safely removing entities from both SimPro and GHL
- β
- β π SEARCH & PREVIEW:
- β Search for Jobs, Quotes, or Sites by ID or name
- β Preview shows EVERYTHING that will be deleted (cascade view)
- β Shows linked GHL Opportunities, Custom Objects, and Associations
- β Site deletion shows all child Jobs and Quotes that will also be removed
- β
- β π‘οΈ SAFETY FEATURES:
- β Admin-only access - regular users cannot access deletion manager
- β Soft-delete by default - items can be restored within configurable window (7-90 days)
- β Must type "DELETE" to confirm soft-delete, "PERMANENT" for permanent delete
- β Invoiced jobs are BLOCKED from deletion - must archive in SimPro instead
- β Full audit trail of all deletion actions with user and timestamp
- β Data snapshots stored for potential restore
- β
- β β»οΈ RESTORE & PERMANENT DELETE:
- β Restore items from deletion queue within the expiry window
- β Restored items get new IDs (SimPro limitation) with updated sync_links
- β Permanent delete clears all snapshots - cannot be undone
- β Auto-expiry cron job permanently deletes items past their restore window
- β
- β π NEW DATABASE TABLES:
- β deletion_queue - tracks all deletion requests, status, and snapshots
- β deletion_audit_log - full audit trail of all actions
- β Tables auto-created on first access
v1.8.9
6 Apr 2026
π·οΈ Fix Duplicate Tags, Zombie Records & Attachment Display
- β FIX #1: Tags syncing from GHL to SimPro were creating massive duplicates
- β Example: Dozens of identical "schools" tags with different IDs
- β Root cause: findOrCreateSimproTagIds() was auto-creating tags when lookup failed
- β Function now ONLY matches existing SimPro tags - never creates new ones
- β Added whitespace trimming to tag name normalization for more robust matching
- β To sync new tags, first create them manually in SimPro (Setup β Tags)
- β
- β FIX #2: Zombie record prevention (e.g., "Places for People" recreating)
- β When updating a job/quote returns 404 (deleted in SimPro), the stale link is now cleared
- β Removes orphaned references from opportunity_job_links and opportunity_quote_links
- β Prevents the system from holding references to deleted SimPro entities
- β
- β FIX #3: Gallery showing attachments that have been removed from server
- β Files cleaned up after Drive sync were still appearing in the gallery
- β Added WHERE clause filter: only show attachments where file_path is not empty
- β Removed attachments no longer clutter the gallery view
v1.8.8
30 Mar 2026
π’ Company Customer Contact Fallback
- β FIX: Jobs/Quotes for company customers were not creating GHL contacts or opportunities
- β Company customers in SimPro often have empty Email/Phone fields on the company record itself
- β Contact details are stored on the company's Contacts (people like "Jackie" or "Joe")
- β SimProSync was checking customer.Email which was empty, so no GHL contact could be upserted
- β Without a GHL contact, no opportunity could be created or linked
- β NEW: Fallback logic for company customer email/phone
- β When customer.Email is empty, now checks customer.Contacts array
- β Prioritises the Primary Invoice Contact (PrimaryInvoiceContact: true)
- β Falls back to first contact with an email if no primary is set
- β Also auto-populates firstName/lastName from the selected contact
- β Example: "Company name Ltd" with empty Email now uses "contact@companyname.com" from contact
- β Logging shows: "π§ Auto-populated email from company contact (contact): contact@companyname.com"
v1.8.7
30 Mar 2026
π§Ύ Invoice Status β Job Opportunity Sync
- β FIX: When marking an invoice as paid, linked job opportunities were not updating in GHL
- β SimPro automatically changes job status to "Job : Invoice Fully Paid" when invoice is paid
- β But SimProSync was not syncing this status change to the GHL opportunity
- β Root cause: invoice.status event type was not triggering opportunity stage sync
- β NEW: invoice.status now triggers opportunity stage updates for associated jobs
- β When invoice.status or invoice.updated fires, fetches all associated jobs from invoice.Jobs array
- β For each job, fetches current job data to get latest status (e.g., "Job : Invoice Fully Paid")
- β Looks up linked GHL opportunity for each job
- β Updates opportunity stage based on job's current status using existing pipeline mappings
- β Supports invoices linked to multiple jobs (processes each one)
- β New logging section: invoice_job_sync shows each job processed and result
- β Example: Invoice paid β Job #8221 status becomes "Job : Invoice Fully Paid" β GHL opportunity moves to mapped stage
v1.8.6
25 Mar 2026
π§ company_id=0 Bug Fixes & Settings Test Buttons
- β FIX: Multiple files failed for single-company SimPro accounts (company_id = 0)
- β PHP treats 0 as "falsy", so checks like !$companyId or empty($companyId) incorrectly failed
- β Fixed in: mappings_pipeline.php, fetch_simpro_attachments.php, force_sync.php, dropdown_resolver.php
- β All single-company SimPro setups (like Safespark) now work correctly
- β NEW: Test API Connection buttons on Settings page
- β Each integration now has "Test SimPro Connection" and "Test GHL Connection" buttons
- β SimPro test calls /setup/statusCodes/projects/ to verify credentials
- β GHL test calls /locations/{locationId} to verify API access
- β Shows success (green) with status count or location name
- β Shows failure (red) with specific error message and fix instructions
- β Helps diagnose 401 (wrong API key) vs 404 (wrong company ID) errors
- β IMPROVED: Snapshot system now captures source status cache
- β create_snapshot.php now stores source_status_cache when snapshotting pipeline mappings
- β Contains status_id β status_name mapping from source SimPro
- β Enables future status ID remapping when applying to different SimPro instances
- β Note: Status remapping only works when SimPro instances have matching status NAMES
- β Different SimPro setups with custom statuses will need manual pipeline/status mapping
- β Snapshot version bumped to 2.3
v1.8.4
25 Mar 2026
πΈ Comprehensive Snapshots & Multiple Fixes
- β FIX: apply_snapshot.php was using wrong column names for association labels
- β Changed first_object_key/second_object_key β input_schema/output_schema to match actual DB schema
- β FIX: Association mappings were looking for "is_enabled" but snapshot contains "enabled"
- β FIX: Status mappings INSERT was completely wrong schema β fixed to match ghl_status_mappings table
- β Correct columns: integration_id, custom_object_key, field_type, simpro_value, simpro_status_id, ghl_value, display_order
- β FIX: Pipeline mappings now includes all columns from snapshot (simpro_status_id, simpro_status_ids, archive_reason_id, sync_direction, is_primary, is_default_for_new)
- β Snapshots can now be successfully applied to new integrations like Safespark
- β NEW: Snapshots now include ALL mapping types for complete account cloning
- β Added: Association Mappings (ContactβSite, SiteβProject, etc.)
- β Added: Association Labels (GHL custom object association definitions)
- β Added: Pipeline Stage Mappings (GHL stages β SimPro stages)
- β Added: Status Mappings (SimPro status values β GHL dropdown values)
- β Snapshot version bumped to 2.2 to reflect new comprehensive structure
- β NEW: Events are now ENABLED by default when applying snapshots
- β Previously, if source account had disabled events, applied accounts inherited disabled state
- β New accounts created from snapshots now start with all events active immediately
- β FIX: Status Mappings page failed for single-company SimPro accounts
- β company_id = 0 is valid for single-company setups, but PHP treated it as "falsy"
- β Changed check from if($companyId) to if($companyId !== null && $companyId !== '')
- β SimPro statuses now load correctly for ALL accounts regardless of company_id value
- β FIX: Settings page now respects user permissions
- β Cloud Storage section (Google Drive, Dropbox) hidden when user lacks permission
- β Auto-Sync settings hidden when google_drive permission is disabled
- β Permissions loaded from user_permissions table and checked before rendering sections
- β NEW: Opportunity name automatically syncs to Quote/Job name in SimPro
- β Name changes are detected independently β no stage change required
- β When you rename an opportunity in GHL, the linked quote/job name updates in SimPro automatically
- β New syncOpportunityNameToSimpro() function handles name-only updates
- β Last known name stored in ghl_opportunity_name column for change detection
- β Works for both quotes and jobs
- β DB: Added ghl_opportunity_name column to opportunity_quote_links and opportunity_job_links tables
- β UI: New "Additional Mappings" section in Create Snapshot modal
- β UI: Info boxes explain snapshot behavior and event enabling
- β UI: Association, Pipeline, and Status mappings checked by default when creating snapshots
v1.8.3
24 Mar 2026
β‘ SimPro Webhook Timeout Prevention
- β FIX: SimPro webhooks failing with HTTP 408 (Request Timeout) during bulk operations
- β SimPro was timing out waiting for SimProSync to respond while processing was still running
- β NEW: Implemented fastcgi_finish_request() pattern in webhook_simpro.php
- β Webhook endpoint now sends 200 OK immediately upon receiving valid JSON
- β Processing continues in background after SimPro connection is closed
- β Eliminates 408 errors even when enrichment requires 20-30 API calls
- β Database logging still captures full processing results via shutdown function
- β FIX: PHP warning "Undefined variable $ghlContactId" in webhook_processor.php
- β Variable was referenced in diff logging section before being initialized
- β Added proper initialization: $ghlContactId = null before the logging block
- β Server timeout configuration also increased (max_execution_time: 300s, nginx proxy timeouts: 300s)
v1.8.2
24 Mar 2026
π§ Server Timeout Configuration
- β INFRASTRUCTURE: Increased PHP max_execution_time from 30s to 300s
- β INFRASTRUCTURE: Added nginx proxy timeout directives (300s) for webhook endpoints
- β Prevents 504 Gateway Timeout errors during bulk SimPro operations
- β Each webhook with full enrichment can require 10-15 seconds of API calls
- β Bulk updates (e.g., updating many jobs at once) previously caused server to become unresponsive
- β Note: This changelog entry documents server-side Plesk configuration changes
v1.8.1
17 Mar 2026
π― Auto-Create Opportunity Fix
- β FIX: Auto-create opportunity logic was incorrectly blocking opportunity creation
- β The "auto_create_opportunity" setting was being checked for ALL jobs/quotes, not just new contacts
- β This caused opportunities to NOT be created when jobs/quotes came in for existing GHL contacts
- β REMOVED: The setting check wrapper that was blocking createGhlOpportunity() calls
- β Now opportunities are created for ALL jobs/quotes that have a valid GHL contact linked
- β The original intent was to control opportunity creation for brand new contacts only
- β Existing contact workflows now work correctly: Job created in SimPro β Opportunity created in GHL
- β No changes to association logic, custom object sync, or field mappings
v1.8.0
16 Mar 2026
π Opportunity Custom Fields & Company Customer Fixes
- β FIX: Opportunity custom fields now sync from SimPro to GHL
- β Previously, mappings for opportunity.* fields (SimPro Job ID, Opportunity Value, Site ID, etc.) were ignored
- β Code was only handling contact.*, custom_objects.*, and contact.phone.* fields
- β NEW: Mapping loop now collects opportunity.* fields into $opportunityFieldMappings array
- β Opportunity fields are written when creating new opportunities (if auto-create enabled)
- β Opportunity fields are written when updating existing linked opportunities
- β Field ID lookup tries both "opportunity.fieldname" and "fieldname" formats (GHL API compatibility)
- β FIX: Company customer sites URL now includes customer type (GHL β SimPro direction)
- β Previously, creating quotes/jobs from GHL failed for Company customers with 404 errors
- β Sites endpoint was using /customers/{id}/sites/ instead of /customers/companies/{id}/sites/
- β Now correctly detects customer type and uses appropriate endpoint
- β Applies to: createSimproQuote(), createSimproEntityFromProject(), and related functions
- β NEW: "Opportunity Custom Fields" section in SimPro Logs page
- β Shows which opportunity fields were collected and their values
- β Helps debug opportunity field sync issues
- β Processing Steps now show: "π Collected opportunity field: opportunity.simpro_job_id = 12345"
v1.7.9
5 Mar 2026
π’ Company Contact Fallback & Mapping-Driven Opportunity Value
- β NEW: Company customer contact fallback for SimProβGHL direction
- β Previously, jobs linked to Company customers with no direct email/phone failed with "No email or phone available"
- β System now detects when customer is a Company with blank contact details
- β Falls back to the job's CustomerContact (the specific person assigned to the job)
- β Fetches full contact details from SimPro: /customers/{id}/contacts/{contactId}
- β Extracts email, phone (CellPhone or WorkPhone), firstName, lastName from the contact record
- β Enables contact upsert, opportunity sync, and project/site associations for Company customer jobs
- β Fallback only activates when email AND phone are both empty β no impact on Individual customers
- β Clear logging: "π§ Using CustomerContact email (company fallback): ..."
- β NEW: Mapping-driven opportunity value sync
- β Opportunity value (monetaryValue) is now read from ghl_field_mappings for the lead_value field
- β Customers can map any SimPro value field to GHL opportunity value via the Mappings UI
- β Falls back to Total.ExTax β Total.IncTax if no mapping configured
- β New helper function: getOpportunityValueFromMappings() used in both createGhlOpportunity() and stage sync
- β FIX: Dropdown resolver now removes unresolvable dropdown values from payload entirely
- β Previously, invalid dropdown values were left in the payload causing SimPro API errors
- β Acts as a safety net for customer misconfiguration of dropdown field mappings
v1.7.8
3 Mar 2026
π’ Company Customer Support & Customer Type Storage
- β FIX: Customer updates now work for BOTH Individual and Company customers
- β Previously, all customers were assumed to be Individuals, causing 404 errors when updating Company customers
- β NEW: simpro_customer_type column in sync_links table stores customer type (individuals/companies)
- β Customer type is now stored when a customer is created via GHLβSimPro sync
- β When updating, system checks sync_links first for stored type (avoids extra API call)
- β If type not stored, detects from SimPro API and stores for future use
- β NEW: Helper functions: getStoredCustomerType(), storeCustomerType(), detectSimproCustomerType()
- β Detection logic improved: checks SimPro Type field AND CompanyName presence
- β Company customers now correctly use /customers/companies/ endpoint
- β Individual customers continue using /customers/individuals/ endpoint
- β Backwards compatible: Existing sync_links records without type will auto-detect on next update
- β FIX: PHP parse error in webhook_processor.php (duplicate empty function declaration)
- β FIX: Undefined variable $ghlContactId warning in webhook_processor.php diff logging section
v1.7.7
3 Mar 2026
π Site Deduplication - Prevent Duplicate GHL Sites
- β FIX: Duplicate Sites created when manually adding Sites in GHL before SimPro sync
- β NEW: Multi-level Site deduplication in SimProβGHL direction
- β Level 1: Check site_sync_links table for existing link by SimPro Site ID
- β Level 2: Search GHL by site_id field (catches Sites created by SimProSync)
- β Level 3: Search GHL by site_name field (catches manually created Sites)
- β Level 4: Search GHL by site_address + site_postal_code (catches Sites with different names but same location)
- β When match found: Updates existing Site and writes SimPro Site ID to link them
- β Only creates new Site if ALL dedup checks fail
- β NEW: getGhlObjectRecord() helper function for fetching GHL custom object records
- β Logs clearly show which dedup method matched: "Found existing Site by name/address+postcode"
v1.7.6
3 Mar 2026
π·οΈ Tags Sync Fix & Webhook 500 Error Resolution
- β FIX: Tags now sync correctly to SimPro (was sending tag names, now sends tag IDs)
- β SimPro API requires Tags as array of integer IDs, not string names
- β NEW: findOrCreateSimproTagIds() function resolves tag names to SimPro Tag IDs
- β Auto-creates tags in SimPro if they don't exist (via POST /setup/tags/)
- β Tags from GHL (comma-separated string) are parsed, resolved to IDs, and sent correctly
- β FIX: 500 error on SimPro β GHL webhooks caused by function redeclaration
- β Wrapped duplicate functions with function_exists() checks to prevent conflicts
- β Affects: webhook_processor.php and functions.php sharing common functions
- β Loop prevention confirmed working: 60-second throttle prevents infinite sync loops
v1.7.5
2 Mar 2026
ποΈ Dynamic Custom Object Mapping & Flexible Entity Types
- β NEW: Dynamic GHL Custom Object Mapping in Settings page
- β Users can now map ANY GHL custom object to ANY SimPro entity type (Sites, Projects, Quotes, Jobs, Leads, Invoices)
- β No longer limited to hardcoded "sites" and "projects" object names
- β Settings UI shows a table of all discovered custom objects with dropdown to select SimPro entity type
- β Auto-detection: Object names containing "site/location/property" default to Sites, "project/job/work" default to Projects, etc.
- β Mappings stored in new ghl_custom_object_mappings database table
- β NEW: SimPro entity type inference from GHL custom object key
- β When custom object webhook arrives, system looks up configured entity type
- β Falls back to smart detection based on object name if no mapping configured
- β Unified webhook handler now routes to correct SimPro entity creation based on mapping
- β FIX: Custom object field mappings now load correctly in GHL Mappings UI
- β Field dropdowns now populate with custom object properties
v1.7.4
1 Mar 2026
π Enhanced Association System & Object-to-Object Links
- β NEW: Object-to-Object associations (Sites β Projects) now fully supported
- β Previously only Contact β Custom Object associations were created
- β System now creates associations between custom objects when both exist
- β Example: When a Quote syncs with Site, the Quote's Project is linked to the Site
- β NEW: Association processing split into two phases
- β Phase 1: Contact β Custom Object associations (immediate)
- β Phase 2: Object β Object associations (after all objects processed)
- β Ensures both objects exist before attempting to link them
- β FIX: Association errors no longer block the main sync process
- β Errors are logged but processing continues
- β Clear logging shows which associations succeeded, failed, or were skipped
v1.7.3
28 Feb 2026
π Site Sync Improvements & Address Handling
- β FIX: Site address fields now sync correctly to GHL custom objects
- β Site address, city, state, postal code, and country now map to corresponding GHL fields
- β NEW: Automatic site sync when job/quote has associated site
- β When a job or quote syncs, its linked Site is automatically synced to GHL
- β Site β Contact association created automatically
- β Site β Project association created if project exists
- β FIX: Site sync no longer fails when Site has no address data
- β Empty address fields are handled gracefully
- β NEW: site_sync_links table tracks SimPro Site ID to GHL Site custom object ID
- β Prevents duplicate Site creation on subsequent syncs
v1.7.2
25 Feb 2026
π Loop Prevention Enhancements
- β FIX: Loop prevention now correctly handles rapid sequential webhooks
- β Previous 60-second throttle was too aggressive for legitimate batch updates
- β NEW: Smart entity comparison - only blocks if Stage AND Status unchanged
- β Allows legitimate updates while still preventing infinite loops
- β NEW: GHL echo detection via sync_links table
- β When GHL webhook arrives, checks if we just sent that update
- β Prevents "we changed it β GHL echoed it β we changed it again" loops
- β Improved logging shows exactly why a webhook was blocked or allowed
v1.7.1
20 Feb 2026
π Enrichment Optimization & Hash-Based Skip
- β NEW: Hash-based enrichment optimization for SimProβGHL direction
- β Hashes webhook payload + enrichment data to detect duplicate content
- β Skips processing if hash matches recent webhook (within 24 hours)
- β Significantly reduces unnecessary GHL API calls
- β NEW: webhook_data_hashes table stores recent hashes with auto-cleanup
- β Hashes auto-expire after 24 hours to prevent table bloat
- β Clear logging: "βοΈ Skipping - identical data recently processed (hash: abc123)"
- β FIX: Enrichment no longer fetches data that won't be used
- β Only fetches related entities that have active field mappings
v1.7.0
15 Feb 2026
π Unified GHL Webhook Handler
- β NEW: Single unified webhook endpoint for ALL GHL events
- β Replaces multiple individual webhook handlers
- β All GHL webhooks now route through actions/webhook_ghl_unified.php
- β Simplified webhook configuration - one URL for all events
- β NEW: Modular architecture with separate helper files
- β core/ghl/discovery.php - GHL API discovery and custom fields
- β core/ghl/simpro_api.php - SimPro API calls
- β core/ghl/ghl_api.php - GHL API calls
- β core/ghl/enrichment.php - Data enrichment logic
- β core/ghl/pipeline.php - Pipeline stage handling
- β core/ghl/payload_builder.php - SimPro payload construction
- β core/ghl/helpers.php - Utility functions
- β core/ghl/simpro_dedup.php - SimPro deduplication
- β Improved error handling and logging throughout
v1.6.0
10 Jan 2026
SimPro β GHL Webhook Processor
- β NEW: SimPro β GHL webhook processor with full enrichment
- β Enriches SimPro webhooks with customer, site, job history, quotes, invoices, notes
- β Smart field mapping from SimPro fields to GHL contact and custom fields
- β Pipeline stage sync from SimPro job/quote stages to GHL opportunity stages
- β Opportunity creation and linking with jobs/quotes
- β Contact β Site β Project associations in GHL
v1.5.8
26 Dec 2025
Company vs Individual Customer Payload Fix
- β Fixed HTTP 422 errors when creating Company customers
- β Company customers no longer send GivenName/FamilyName at top level
- β Individual customers no longer send nested "contact" object
- β Fixed cascade customer creation in site.create and job.create
- β Fixed fallback CREATE scenario payload cleanup
v1.5.7
25 Dec 2025
GHL β SimPro Custom Object Create Fix
- β Fixed site.create_object was not looking up Customer ID from associated contact
- β Fixed job.create_object was not looking up Customer ID from associated contact
- β Fixed quote.create_object was not looking up Customer ID from associated contact
- β Fixed lead.create_object was not looking up Customer ID from associated contact
- β All *.create_object handlers now properly call getSimproCustomerIdFromAssociatedContact()
- β Sites, Jobs, Quotes, and Leads can now be created from GHL custom objects when linked to a contact
v1.5.6
25 Dec 2025
Object-to-Object Associations Fix
- β Fixed Sites β Projects associations not being called
- β Association functions are now properly invoked after successful API calls
- β Improved logging for association creation
v1.5.0
20 Dec 2025
Enrichment Engine & Smart Mapping Analysis
- β Added GHL Enrichment Engine - fetches full contact, business, opportunities, and custom objects
- β Smart Mapping Analysis now shows all available fields from enriched data
- β Improved field lookup with unified GHL data
- β Added support for custom object properties in mappings
v1.4.0
13 Dec 2025
Quote Creation, ID Writebacks & Safety Checks
- β Fixed quote creation - Customer now sent as integer, auto-fetches Site/Type/Name
- β Fixed enrichment to use correct contact_id instead of opportunity ID
- β Added Company vs Individual customer auto-detection
- β Improved Contact events handling (separate from Customer events)
- β Added safety check to prevent accidental mapping deletion
- β Fixed Site ID writeback API URL bug
- β Added Job ID writeback for custom objects
- β Added Quote ID writeback for custom objects
- β Added smart fallbacks for site_id, job_id, quote_id field names
- β Removed debug logging code
v1.3.0
10 Dec 2025
Site Update Fixes & Log Improvements
- β Fixed site update failures - removed trailing slashes from PATCH URLs
- β Fixed site.create_object payload structure
- β Improved log display with loop prevention detection
- β Added "No Action" status display
- β Added detailed SimPro API Calls section in logs
v1.2.0
8 Dec 2025
Site ID Writeback & Dynamic Field Mapping
- β Made Site ID writeback fully dynamic using ghl_field_mappings table
- β Supports any custom object name and field name
- β Improved association handling between custom objects and contacts
v1.1.0
1 Dec 2025
Pipeline Stage Mapping
- β Added bi-directional pipeline stage sync
- β SimPro job stages now sync to GHL opportunity stages
- β GHL opportunity stage changes sync back to SimPro
- β Added pipeline stage mapping configuration page
v1.0.0
15 Nov 2025
Initial Release
- β Bi-directional sync between SimPro and GoHighLevel
- β Customer, Site, Job, Quote, Lead, Invoice sync
- β Custom object support
- β Field mapping configuration
- β Event toggle controls
SimProSync by My Local Trades