Skip to content

feat(integrations): add Bit CRM integration with triggers and actions - #203

Open
RishadAlam wants to merge 17 commits into
mainfrom
feat/bit-crm
Open

feat(integrations): add Bit CRM integration with triggers and actions#203
RishadAlam wants to merge 17 commits into
mainfrom
feat/bit-crm

Conversation

@RishadAlam

Copy link
Copy Markdown
Member

Description

Adds a complete Bit CRM integration (free tier) to Bit Integrations. This includes 47 trigger hooks across 8 CRM entities (Leads, Contacts, Companies, Deals, Products, Tags, Notes, Activities, Invoices) and full CRUD actions for the same entities, enabling two-way automation between Bit CRM and any connected platform.

Motivation & Context

Bit CRM users need the ability to automate workflows based on CRM events and push data into the CRM from external sources. This integration bridges that gap, providing both trigger events and action endpoints for the entire Bit CRM entity model.

Type of Change

  • ✨ New feature
  • 🐛 Bug fix
  • 🔄 Code refactor

Key Changes

Triggers (backend/Triggers/BitCrm/)

  • Added 47 WordPress do_action hooks covering:
    • Leads: created, updated, trashed, converted to contact, tag attach/detach (single + bulk)
    • Contacts: created, updated, trashed, tag attach/detach (single + bulk)
    • Companies: created, updated, trashed, tag attach/detach (single + bulk)
    • Deals: created, updated, trashed, stage updated, tag attach/detach (single + bulk)
    • Products: created, updated, trashed, tag attach/detach (single + bulk)
    • Tags: created, updated, deleted
    • Notes: created, updated, deleted
    • Activities: created, updated, status updated, deleted
    • Invoices: created, updated, status updated, trashed
  • Added normalizeData and csvList helpers for consistent data formatting
  • Added success response wrapper so Record API returns record data on success

Actions (backend/Actions/BitCrm/)

  • Added create/update actions for: Lead, Contact, Company, Deal, Product, Note, Activity, Invoice
  • Added BitCrmActionHelper with centralized entity creation/update logic and tag handling
  • Added dynamic dropdown loaders: currencies, deal stages, invoice terms, contacts, companies, tags (per module)
  • Added mergeConfiguredValues for injecting fixed-values from utility settings
  • Added normalize helper for consistent option formatting

Frontend (frontend/src/components/AllIntegrations/BitCrm/)

  • Added full integration wizard: Authorization → Entity/Action selection → Field mapping → Save
  • Added entity-aware step flow (action selects drive available fields and options)
  • Added field-map validation: required fields check, missing dropdown selection check
  • Added edit mode support via EditBitCrm.jsx
  • Registered BitCrm as a custom form integration in webhookIntegrations.js
  • Added BitCrm to trigger/action selector dropdowns in NewInteg.jsx, EditInteg.jsx, IntegInfo.jsx
  • Added integration icon asset

Bug Fixes

  • Fixed undefined bit_integrations_get_class calls during flow execution
  • Fixed field-map dropdown broken on edit mode
  • Fixed *_id and new_tags fields incorrectly extracted as systemValues during entity creation

Refactors

  • Renamed getAllTasks/tasks to getAllEvents/events for clarity
  • Replaced anonymous hook callbacks with meaningful named handler methods
  • Removed unused filter-based Hooks.php, consolidated to do_action only
  • Tidied BitCrmActionHelper and RecordApiHelper for consistency

Checklist

  • Code follows project style guidelines
  • Self-review completed
  • Tests added/updated
  • Documentation updated if needed
  • README updated if needed

Changelog

  • New Feature: Bit CRM integration (free tier) with 47 trigger events and 16 action endpoints for Leads, Contacts, Companies, Deals, Products, Tags, Notes, Activities, and Invoices.
  • Improvement: Triggers use WordPress do_action for reliable event delivery; dynamic dropdowns auto-populate entity lists and configuration options.
  • Improvement: Field-map validation ensures required fields are mapped before saving a flow.
  • Fix: Resolved undefined function calls during flow execution and corrected field-map behavior in edit mode.

New integration for Bit CRM (leads, contacts, companies, deals, products,
tags, notes, activities, invoices), fully in the free tier — no pro addon
required.

Backend:
- Triggers/BitCrm: BitCrmController (custom_form_submission, 51 wp_hook
  entries), Hooks.php, Routes.php
- Actions/BitCrm: BitCrmActionHelper (31 write methods), Hooks.php (31
  Hooks::filter, all 10,2), RecordApiHelper switch (31 cases), Routes.php
- Core/Util/AllTriggersName.php: BitCrm entry, isPro:false

Frontend:
- AllIntegrations/BitCrm: staticData (31 modules + field maps),
  BitCrmCommonFunc, Authorization/FieldMap/IntegLayout/BitCrm/EditBitCrm jsx
- Registered in NewInteg/EditInteg/IntegInfo/SelectAction (is_pro:false)
- bitCrm.webp logo

Wiring verified: Free withPrefix('bitcrm_*') === Pro-side withFreePrefix
convention (same VAR_FREE_PREFIX), 31 filters/handlers/apply-calls all
match at 2 args, 0 orphan field keys.
…BitCrm in flow UI

BitCrmController used a non-existent bit_integrations_get_class() helper
in every handler, causing a fatal error on any trigger. Replaced with
direct Helper/Flow imports (matching BitSocialController), and moved
prepareFetchFormatFields() formatting into flowExecute() so handlers just
pass raw data.

Also add BitCrm to the featured integrations list in SelectAction/SelectTrigger.
Replace generic $arg1/$arg2/$arg3 with $lead/$tag/$leadId/$stage/
$newStatus/$oldStatus etc. across all 51 trigger handlers, matching
bit-pi's original BitCrmTrigger.php naming.
bitCrmFields was stored on conf only when the action select changed
(handleMainAction). Editing a saved integration restores mainAction and
field_map from the server but never bitCrmFields, so requiredFlds/
nonRequiredFlds resolved to [] and the field-select dropdown rendered
with zero options.

Derive bitCrmFields from bitCrmStaticData[mainAction] on every render
instead of caching it in conf, and pass it into BitCrmFieldMap as a prop.
Fixes both Create and Edit.
- triggers: 17 created/updated handlers used empty(${arg1}) (variable-
  variable → fatal on every fire, and surfaced errors on normal CRM saves);
  replace with each handler's real param ($contact, $deal, …)
- convert_lead: convertToDeals() was called with no argument
  (ArgumentCountError → convert always rolled back); pass the inserted
  contacts from convertToContacts()
- update actions: drop the Tags dropdown — the CRM update() ignores tags
  and the payload never forwarded them (silently dead)
- create_activity: omit due_date when empty (was ''), which MySQL strict
  mode rejects for the nullable datetime column
- create_invoice: drop currency from the required list (the CRM ignores
  invoice currency, so requiring it was savable-but-broken)
- remove the now-unused refresh_bitcrm_users route + refreshUsers() (owner
  and assigned_to became email fields)
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@github-actions

Copy link
Copy Markdown

🔍 WordPress Plugin Check Report

⚠️ Status: Passed with warnings

📊 Report

🎯 Total Issues ❌ Errors ⚠️ Warnings
1 0 1

⚠️ Warnings (1)

📁 readme.txt (1 warning)
📍 Line 🔖 Check 💬 Message
0 mismatched_plugin_name Plugin name "Bit integrations - Form Integration, Webhook, Spreadsheets, CRM, LMS & Email Automation" is different from the name declared in plugin header "Bit Integrations".

🤖 Generated by WordPress Plugin Check Action • Learn more about Plugin Check

Bit-Pi grew 23 write actions that never made it across: update/delete for
tags and notes, the full task, meeting and call set, invoice update, status
and delete, and the four client portal actions. Port them all, keeping the
free-tier architecture BitCrm already uses (RecordApiHelper switch calling
BitCrmActionHelper directly, is_pro false), rather than routing them through
a Pro hook like most integrations do.

Activity actions verify the record type before touching it, so Delete Task
refuses a meeting id. Updates are partial: an empty field keeps the current
value. Invoice writes honour Bit CRM's rules that paid invoices are locked
and status moves must be legal transitions, and delete soft-deletes into the
trash bin.

Target identifiers stay in the field map so they can be mapped from trigger
data; enums and capability lists are selects, and is_shared is a Utility.

BREAKING CHANGE: create_activity is retired in favour of create_task,
create_meeting and create_call. Flows still using it will log Invalid action
and must be rebuilt.
Bit CRM fires one hook for tasks, meetings and calls alike, because they
share the activities table and differ only by type. Dispatch both the
generic event and a type-specific one, so a flow can subscribe at whichever
granularity it needs. The generic events still fire, so saved flows keep
working.

The typed ids are flow keys, not WordPress hooks — no such hook exists.
Activity Deleted stays generic: Bit CRM hard-deletes the row before firing
and passes only the id, so the type can no longer be resolved.

Attachments and links were fired by Bit CRM but listened to by nobody; wire
up their five hooks too.
Selects are stored flat on conf and switching action only reset mainAction
and field_map, so values the previous action wrote stayed behind. Several
keys share a Bit CRM field — productStatus, activityStatus and invoiceStatus
all write status, as dealType/productType write type — and the last one
merged won. Configuring Update Task Status and then switching to Create
Product created the product with status completed instead of active.

Fix both ends: the layout now drops every select and utility key the new
action does not render, and the merge refuses a key whose action list does
not contain the chosen action, so a conf saved by the old code cannot
corrupt a record either.

Also report unresolved owner and assignee emails by name, instead of letting
them surface downstream as a bare "assigned_to is required", and note on
Update Invoice that existing line items keep their original tax mode.
Bit CRM Pro now fires client_portal_access_granted and
client_portal_access_revoked, each carrying the contact and the portal email.
Revoking works from a WordPress user, so its contact can be null when the
portal account has no matching CRM contact; the email is the only value both
events always carry, and the payload is the contact's fields plus that email.

These live in Bit CRM Pro, so they stay silent on a Free-only install.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant