feat: Implement Salesforce to DocuSign contract automation integration - #58
feat: Implement Salesforce to DocuSign contract automation integration#58iamvirul wants to merge 51 commits into
Conversation
- Added integration prompt detailing the functionality and requirements for automating contract dispatch from Salesforce to DocuSign. - Created README.md with setup instructions, prerequisites, and configuration details for Salesforce and DocuSign. - Developed agents.bal for future AI-powered features, including opportunity complexity analysis and intelligent template selection. - Implemented automation.bal for core logic to create and send DocuSign envelopes based on Salesforce opportunity updates. - Configured connections.bal for Salesforce and DocuSign client initialization. - Established data_mappings.bal for transforming Salesforce data to DocuSign format. - Added functions.bal for retrieving opportunity and contact details from Salesforce. - Created main.bal to handle Salesforce listener events for opportunity changes. - Defined types.bal for Salesforce and DocuSign data structures, including opportunity, contact, and template configurations. - Introduced error handling and logging throughout the integration for better observability.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a Ballerina integration that listens for Salesforce Change Events and automates DocuSign envelope creation: types, configuration, client connections, listener service, orchestration and helpers, AI scaffolding, documentation, and Choreo metadata. Changes
Sequence DiagramsequenceDiagram
participant Salesforce as Salesforce (Change Event)
participant Listener as SalesorceListener
participant Processor as ContractProcessor
participant SF_API as Salesforce API
participant DS_API as DocuSign API
Salesforce->>Listener: onUpdate(eventData)
Listener->>Processor: processOpportunityForContract(opportunityId)
Processor->>SF_API: getOpportunity(opportunityId)
SF_API-->>Processor: Opportunity
Processor->>Processor: validate & meetsDispatchCriteria
Processor->>SF_API: getContactByRole / getPrimaryContact (fallback)
SF_API-->>Processor: Contact
Processor->>Processor: selectTemplate, buildTemplateFields, buildEnvelope
Processor->>DS_API: createAndSendEnvelope(envelopeDefinition)
DS_API-->>Processor: envelopeId / status
Processor->>SF_API: updateOpportunityStage(opportunityId, "Contract Sent", envelopeId)
SF_API-->>Processor: updateResult
Processor-->>Listener: complete (log)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (2)
ballerina-integrator/salesforce-closewon-contract-automation/.choreo/instructions.md (1)
51-62: Consider differentiating heading names across sections.Static analysis flagged duplicate headings ("Prerequisites" and "Setup Steps") appearing in both Salesforce and DocuSign setup guides. While they're in separate collapsible sections, unique headings (e.g., "DocuSign Prerequisites") would improve navigation and anchor-link uniqueness.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/.choreo/instructions.md` around lines 51 - 62, The duplicate top-level headings "Prerequisites" and "Setup Steps" cause ambiguous anchors; update the headings in instructions.md to unique names (e.g., rename the DocuSign section headers from "Prerequisites" and "Setup Steps" to "DocuSign Prerequisites" and "DocuSign Setup Steps") so anchors and navigation are distinct; locate the headings that exactly match "Prerequisites" and "Setup Steps" in the DocuSign collapsible section and rename them consistently, keeping the content intact.ballerina-integrator/salesforce-closewon-contract-automation/agents.bal (1)
12-36: Placeholder functions are not integrated into the workflow.These functions are scaffolding as noted in the comments. However,
recommendTemplatealways returns()and neither function is called by the actual template selection flow (selectTemplateinfunctions.balis used instead perautomation.bal:156).Consider either:
- Adding a TODO comment clarifying these are unused scaffolds pending AI integration
- Removing until actual AI features are implemented to avoid dead code
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/agents.bal` around lines 12 - 36, The two scaffold functions analyzeOpportunityComplexity and recommendTemplate are dead code (recommendTemplate returns empty and neither is called by selectTemplate), so either mark them clearly as unused or remove them; update agents.bal by adding a TODO comment above both functions stating they are unused scaffolds pending AI integration (including reference to selectTemplate and automation.bal where the real flow lives) or delete the functions entirely to avoid dead code—choose one approach and apply consistently so reviewers know these are intentionally not part of the current template selection flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/automation.bal`:
- Around line 34-38: The envelopeDefinition currently only sets emailSubject,
templateId and status so templateConfig.expirationDays never gets sent; update
the code that builds envelopeDefinition (the variable envelopeDefinition) to
include the expiration configuration from templateConfig.expirationDays (attach
it under the DocuSign notification/expiration structure expected by the API) so
the value passed by selectTemplate() and stored on TemplateConfig is forwarded
in the outgoing envelope.
- Around line 170-180: The current getSignerContact implementation always falls
back to getPrimaryContact on any Contact|error from getContactByRole, which
hides real errors and also mis-handles when signerRole == PRIMARY_CONTACT;
change getSignerContact to first check if signerRole == PRIMARY_CONTACT and call
getPrimaryContact directly (use the existing getPrimaryContact), and when
calling getContactByRole(opportunityId, signerRole) only perform the fallback to
primary when the returned error is a typed “not found” error (e.g.,
ContactNotFound or a sentinel error type your code uses) — for all other errors
return the error immediately so auth/query/deserialization failures are
propagated rather than downgraded.
- Around line 159-164: The flow currently calls
createAndSendEnvelope(opportunity, signer, templateConfig) before any durable
marker is written, so retries can produce duplicate envelopes; make this
idempotent by persisting a marker or envelopeId before or atomically with the
send and skipping the send if the marker exists. Concretely: add or extend a
durable check function (e.g., hasEnvelopeOrStage(opportunityId) or
storeEnvelopeMarker(opportunityId, envelopeId)) and call it before
createAndSendEnvelope to short-circuit if an envelope was already recorded; if
you must write a marker before sending, write a “sending_started” marker (via
updateOpportunityStage or a new persistent store function) and only call
createAndSendEnvelope when no marker exists, then update the marker with the
real envelopeId after success; update updateOpportunityStage (or create a new
persistent helper) to perform the durable write/read so retries are safe.
In
`@ballerina-integrator/salesforce-closewon-contract-automation/connections.bal`:
- Around line 12-19: The docusignClient is being created with a static
docusignAccessToken which will expire; replace this with the OAuth2
refresh-token configuration supported by dsesign:Client: remove the static token
usage and initialize docusignClient using clientId, clientSecret, refreshToken
and refreshUrl (and keep serviceUrl = docusignBaseUrl) so the connector can
automatically renew tokens; follow the same pattern used for the Salesforce
client in this file to wire secrets and URLs into the dsesign:Client
constructor.
In
`@ballerina-integrator/salesforce-closewon-contract-automation/data_mappings.bal`:
- Line 70: The info log currently prints raw PII (contact.Email) in the call to
log:printInfo; change that to avoid exposing emails by logging a masked email or
a non-personal identifier instead (for example mask contact.Email before
logging, or log contact.Id or a hash/correlation id). Update the call that
contains log:printInfo(string `Validated contact ${contact.Id}:
${contact.Email}`) to use the masked/hashed value or contact.Id only so no raw
email is emitted.
In `@ballerina-integrator/salesforce-closewon-contract-automation/functions.bal`:
- Around line 122-128: The current updateOpportunityStage function only logs a
message but returns no value, so callers like processOpportunityForContract
treat it as a successful update while Salesforce is unchanged; either implement
the actual Salesforce REST call to patch the Opportunity StageName (and any
required fields) using your Salesforce HTTP client (e.g., perform a PATCH to
/sobjects/Opportunity/{opportunityId} setting StageName to stageName and handle
auth/response), or if you cannot implement it now, change updateOpportunityStage
to return a non-nil error when not implemented so processOpportunityForContract
does not assume success; update the function signature/return path accordingly
and ensure processOpportunityForContract checks and handles the returned error.
- Around line 87-118: The getOpportunityFieldValue function currently returns an
empty string for any fieldName it doesn't recognize, causing silent data loss in
buildTemplateFields; update handling so unknown opportunityField names surface
an error instead of returning "", either by changing getOpportunityFieldValue to
return an error type (e.g., returns string|error) and return a descriptive error
for unknown fieldName, or by adding a validation step in startup that iterates
configured opportunityField values (from config) and uses
getOpportunityFieldValue to verify each one exists, failing fast with a clear
message; reference getOpportunityFieldValue and buildTemplateFields when
implementing the change and include the unknown fieldName in the error text.
- Around line 12-17: Both SOQL queries that populate the OpportunityContactRole
record are missing required Id and OpportunityId fields; update the SELECT
clauses to include Id and OpportunityId so the Ballerina record maps correctly.
Specifically, modify the soqlQuery string used with salesforceClient->query (and
the other similar SOQL string later in the file) to include "Id, OpportunityId"
alongside ContactId and Role/IsPrimary before calling salesforceClient->query
that produces stream<OpportunityContactRole, error?> (or any other variable that
holds that query result).
In `@ballerina-integrator/salesforce-closewon-contract-automation/main.bal`:
- Line 5: The service path is using a custom name "OpportunityChangeListener" so
the salesforceListener never subscribes; change the service declaration to use
the configurable salesforceChannelName as the service path (i.e., declare
service salesforceChannelName on salesforceListener) and ensure the existing
remote methods (onCreate/onUpdate/onDelete or onEvent) remain on that service so
the connector subscribes to the correct CDC channel.
In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md`:
- Around line 109-111: The README currently points to a non-existent Config.toml
which is gitignored; update the docs and repo so users have a usable sample: add
a new file named Config.toml.example (or Config.toml.sample) checked into the
repo containing the required TOML keys/structure, and update README.md (the
installation/run steps) to reference Config.toml.example (or include a short
inline TOML snippet) and instruct users to copy it to Config.toml and fill in
credentials; ensure references to "Config.toml" in README.md are replaced with
the example filename or explicit copy instructions to avoid confusion.
---
Nitpick comments:
In
`@ballerina-integrator/salesforce-closewon-contract-automation/.choreo/instructions.md`:
- Around line 51-62: The duplicate top-level headings "Prerequisites" and "Setup
Steps" cause ambiguous anchors; update the headings in instructions.md to unique
names (e.g., rename the DocuSign section headers from "Prerequisites" and "Setup
Steps" to "DocuSign Prerequisites" and "DocuSign Setup Steps") so anchors and
navigation are distinct; locate the headings that exactly match "Prerequisites"
and "Setup Steps" in the DocuSign collapsible section and rename them
consistently, keeping the content intact.
In `@ballerina-integrator/salesforce-closewon-contract-automation/agents.bal`:
- Around line 12-36: The two scaffold functions analyzeOpportunityComplexity and
recommendTemplate are dead code (recommendTemplate returns empty and neither is
called by selectTemplate), so either mark them clearly as unused or remove them;
update agents.bal by adding a TODO comment above both functions stating they are
unused scaffolds pending AI integration (including reference to selectTemplate
and automation.bal where the real flow lives) or delete the functions entirely
to avoid dead code—choose one approach and apply consistently so reviewers know
these are intentionally not part of the current template selection flow.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: df87ec85-6267-47ce-95d6-21966c356536
📒 Files selected for processing (15)
ballerina-integrator/salesforce-closewon-contract-automation/.choreo/config-schema.jsonballerina-integrator/salesforce-closewon-contract-automation/.choreo/diagram.mdballerina-integrator/salesforce-closewon-contract-automation/.choreo/instructions.mdballerina-integrator/salesforce-closewon-contract-automation/.gitignoreballerina-integrator/salesforce-closewon-contract-automation/Ballerina.tomlballerina-integrator/salesforce-closewon-contract-automation/Dependencies.tomlballerina-integrator/salesforce-closewon-contract-automation/README.mdballerina-integrator/salesforce-closewon-contract-automation/agents.balballerina-integrator/salesforce-closewon-contract-automation/automation.balballerina-integrator/salesforce-closewon-contract-automation/config.balballerina-integrator/salesforce-closewon-contract-automation/connections.balballerina-integrator/salesforce-closewon-contract-automation/data_mappings.balballerina-integrator/salesforce-closewon-contract-automation/functions.balballerina-integrator/salesforce-closewon-contract-automation/main.balballerina-integrator/salesforce-closewon-contract-automation/types.bal
…nd error handling
…ient secret, and refresh token
…error handling for Salesforce updates
…queries for OpportunityContactRole.
…late field construction by returning errors for invalid or missing fields.
…ME with guidance for direct channel path modification.
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
ballerina-integrator/salesforce-closewon-contract-automation/data_mappings.bal (1)
82-84:⚠️ Potential issue | 🟠 MajorAvoid returning raw email in validation errors.
Line 83 includes
contact.Emailin the error message, which can leak PII through logs and traces. Return a generic message (or masked value) instead.Proposed fix
- if !contact.Email.includes("@") { - return error(string `Invalid email format: ${contact.Email}`); - } + if !contact.Email.includes("@") { + string maskedEmail = maskEmail(contact.Email); + return error(string `Invalid email format for contact ${contact.Id}: ${maskedEmail}`); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/data_mappings.bal` around lines 82 - 84, The validation currently returns the raw contact.Email in the error (the if !contact.Email.includes("@") branch); change the error return to avoid leaking PII by returning a generic message like "Invalid email format" or a masked email (e.g., replace the local-part with a single character and asterisks) instead of embedding contact.Email; update the return error(...) expression in that conditional so it emits the safe message while preserving the same error type and flow.ballerina-integrator/salesforce-closewon-contract-automation/automation.bal (1)
217-224:⚠️ Potential issue | 🔴 CriticalDocuSign send is still not durably idempotent.
The irreversible send happens before a durable, retry-safe marker is guaranteed. If the post-send update path fails, retried events can create duplicate envelopes.
Suggested direction
- // Create and send DocuSign envelope - string envelopeId = check createAndSendEnvelope(opportunity, signer, templateConfig); + // Persist a durable "in-flight" marker before send (or reserve an idempotency key) + check markDispatchStarted(opportunityId); + string envelopeId = check createAndSendEnvelope(opportunity, signer, templateConfig); + check markDispatchCompleted(opportunityId, envelopeId);Also ensure
hasEnvelopeAlreadySent()checks both markers.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/automation.bal` around lines 217 - 224, The createAndSendEnvelope call is performed before any durable, retry-safe marker is persisted, so failures after send can cause duplicate envelopes on retry; change the flow to (1) have hasEnvelopeAlreadySent check both the final envelope marker and a durable "pending-send" marker, (2) persist a durable pending marker (e.g., via updateOpportunityStage or a new persistent flag) before calling createAndSendEnvelope, (3) call createAndSendEnvelope, and (4) atomically replace the pending marker with the final envelopeId (or updateOpportunityStage to the "Contract Sent" state with envelopeId); ensure functions referenced—createAndSendEnvelope, updateOpportunityStage, and hasEnvelopeAlreadySent—are updated accordingly to implement the pending→final marker pattern so retries are idempotent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/functions.bal`:
- Around line 12-15: The SOQL is constructed by interpolating opportunityId and
role directly into the soqlQuery string (see the soqlQuery variable and use of
opportunityId/role), which risks malformed queries or injection; instead
validate and whitelist Salesforce IDs (e.g., ensure opportunityId matches the
15/18-char SF ID pattern and role is from an allowed set) before constructing
the query, and build the query using a safe/parameterized approach or escaped
literals; apply the same validation and construction fix to the second
occurrence that interpolates opportunityId/role elsewhere in the file.
- Around line 167-172: The code currently writes the DocuSign envelope marker
into the standard Description field (see envelopeId, envelopeMarker,
updatePayload, opportunityId) which risks overwriting user CRM content; change
the assignment to use a dedicated custom field instead (for example replace
updatePayload["Description"] = envelopeMarker with
updatePayload["DocuSign_Envelope_Id__c"] = envelopeMarker or a configurable
custom-field key), keep the log line as-is, and update comments to reflect that
a custom integration field is used rather than Description.
In `@ballerina-integrator/salesforce-closewon-contract-automation/main.bal`:
- Around line 19-27: The code currently reads the Opportunity ID from
changedData["entityId"]; update it to read from eventData.metadata.recordId
instead (reference eventData and its metadata.recordId field) and change the
failure behavior to fail fast: if recordId is missing or empty log an error ("No
recordId found in Salesforce ChangeEvent metadata") and return an error (not
nil) so downstream logic using opportunityId is not executed; ensure you assign
the value to the existing opportunityId variable and use a non-empty check
before proceeding.
---
Duplicate comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/automation.bal`:
- Around line 217-224: The createAndSendEnvelope call is performed before any
durable, retry-safe marker is persisted, so failures after send can cause
duplicate envelopes on retry; change the flow to (1) have hasEnvelopeAlreadySent
check both the final envelope marker and a durable "pending-send" marker, (2)
persist a durable pending marker (e.g., via updateOpportunityStage or a new
persistent flag) before calling createAndSendEnvelope, (3) call
createAndSendEnvelope, and (4) atomically replace the pending marker with the
final envelopeId (or updateOpportunityStage to the "Contract Sent" state with
envelopeId); ensure functions referenced—createAndSendEnvelope,
updateOpportunityStage, and hasEnvelopeAlreadySent—are updated accordingly to
implement the pending→final marker pattern so retries are idempotent.
In
`@ballerina-integrator/salesforce-closewon-contract-automation/data_mappings.bal`:
- Around line 82-84: The validation currently returns the raw contact.Email in
the error (the if !contact.Email.includes("@") branch); change the error return
to avoid leaking PII by returning a generic message like "Invalid email format"
or a masked email (e.g., replace the local-part with a single character and
asterisks) instead of embedding contact.Email; update the return error(...)
expression in that conditional so it emits the safe message while preserving the
same error type and flow.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 07a1e717-b9be-4634-8a43-d2b0b7c9058a
📒 Files selected for processing (8)
ballerina-integrator/salesforce-closewon-contract-automation/Dependencies.tomlballerina-integrator/salesforce-closewon-contract-automation/README.mdballerina-integrator/salesforce-closewon-contract-automation/automation.balballerina-integrator/salesforce-closewon-contract-automation/config.balballerina-integrator/salesforce-closewon-contract-automation/connections.balballerina-integrator/salesforce-closewon-contract-automation/data_mappings.balballerina-integrator/salesforce-closewon-contract-automation/functions.balballerina-integrator/salesforce-closewon-contract-automation/main.bal
🚧 Files skipped from review as they are similar to previous changes (3)
- ballerina-integrator/salesforce-closewon-contract-automation/Dependencies.toml
- ballerina-integrator/salesforce-closewon-contract-automation/README.md
- ballerina-integrator/salesforce-closewon-contract-automation/config.bal
… data retrieval and update operations to prevent SOQL injection.
…ead of changed data.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
ballerina-integrator/salesforce-closewon-contract-automation/functions.bal (1)
203-208:⚠️ Potential issue | 🟠 MajorDo not store integration metadata in
Description.At Line 207, writing envelope markers to
Descriptioncan overwrite user CRM content. Keep envelope metadata in a dedicated custom field instead.Proposed fix
- string envelopeMarker = string `[DocuSign Envelope: ${envelopeId}]`; - updatePayload["Description"] = envelopeMarker; + updatePayload["DocuSign_Envelope_Id__c"] = envelopeId;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/functions.bal` around lines 203 - 208, The code is writing DocuSign metadata into the CRM Description field (using updatePayload["Description"] and envelopeMarker), which can overwrite user content; change the payload to set a dedicated custom field (e.g., updatePayload["DocuSign_Envelope_Id__c"] = envelopeMarker) instead of "Description", keep the log printInfo for envelopeId and opportunityId unchanged, and remove or avoid writing to updatePayload["Description"] wherever envelopeMarker is set (refer to the envelopeId, envelopeMarker, updatePayload and opportunityId symbols to locate the change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/functions.bal`:
- Around line 214-220: The code currently returns updateResult (an error) from
updateOpportunityStage after the DocuSign envelope has already been sent, which
causes retries and duplicate sends; instead swallow and surface a non-fatal
outcome: in the function that contains the shown block (updateOpportunityStage),
remove the "return updateResult" error propagation and replace it with a
non-error return (e.g., return (); or return a success/partial-failure value) so
the function does not propagate a failure after the envelope dispatch; also
update the caller in automation.bal to stop using "check
updateOpportunityStage(...)" (use a plain call or handle the returned status) so
an update failure won't trigger retry of the send logic.
In `@ballerina-integrator/salesforce-closewon-contract-automation/main.bal`:
- Line 5: The service is subscribing too broadly to "/data/ChangeEvents" on
salesforceListener and should be limited to Opportunity change events; change
the service resource path from "/data/ChangeEvents" to the Opportunity-specific
channel (e.g., "/data/ChangeEvents/OpportunityChangeEvent") so only
OpportunityChangeEvent messages are received and processed by this service
declaration on salesforceListener.
---
Duplicate comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/functions.bal`:
- Around line 203-208: The code is writing DocuSign metadata into the CRM
Description field (using updatePayload["Description"] and envelopeMarker), which
can overwrite user content; change the payload to set a dedicated custom field
(e.g., updatePayload["DocuSign_Envelope_Id__c"] = envelopeMarker) instead of
"Description", keep the log printInfo for envelopeId and opportunityId
unchanged, and remove or avoid writing to updatePayload["Description"] wherever
envelopeMarker is set (refer to the envelopeId, envelopeMarker, updatePayload
and opportunityId symbols to locate the change).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 0f5b5fdb-e0cc-415b-80d0-09579c18a21d
📒 Files selected for processing (2)
ballerina-integrator/salesforce-closewon-contract-automation/functions.balballerina-integrator/salesforce-closewon-contract-automation/main.bal
…EADME.md Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
ballerina-integrator/salesforce-closewon-contract-automation/README.md (1)
114-127: 🛠️ Refactor suggestion | 🟠 MajorRemove local execution instructions per previous feedback.
The "Running Locally" section was flagged for removal in an earlier review. Additionally, line 117 references a gitignored
Config.tomlfile that won't exist in cloned repositories, which was also flagged previously as misleading.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md` around lines 114 - 127, Remove the entire "Running Locally" section (the "## Running Locally" header and its numbered steps) and any references to a gitignored Config.toml or the local command "bal run" from README.md so the file no longer instructs users to run the integration locally or points to a non-existent Config.toml; ensure you also remove the duplicate_comment marker and any duplicated guidance elsewhere in the README to avoid reintroducing the same content.
🧹 Nitpick comments (2)
ballerina-integrator/salesforce-closewon-contract-automation/README.md (2)
39-39: Fix brand name capitalization."Docusign" should be "DocuSign" (capital S). This inconsistency was noted in a previous review.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md` at line 39, Update the heading "Docusign Setup" in the README to use the correct brand capitalization "DocuSign Setup" and scan the README for any other occurrences of "Docusign" to replace them with "DocuSign" to ensure consistent branding throughout.
9-19: Consolidate bullet points to 3-5 as previously requested.The list currently contains 10 bullet points. Based on previous feedback, this should be reduced to 3-5 high-level points. Consider grouping related items (e.g., "validates, retrieves, and selects" into one bullet; "creates envelope with signers, fields, and CCs" into another).
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md` around lines 9 - 19, Condense the README's detailed 10-item feature list into 3–5 high-level bullets by grouping related actions: one bullet for event listening and business validation (Change Data Capture + "Closed Won" & deal value checks), one for data retrieval and template selection (contact lookup by signer role + DocuSign template choice), one for envelope creation (pre-filled fields + configured signer(s) + CC recipients + custom subject/routing), and one for post-send actions and robustness (update Opportunity stage to "Contract Sent" + error handling/logging); update the existing bullet list under the feature summary to replace the 10 bullets with these grouped items so the README remains concise and focused.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md`:
- Line 102: The section heading currently reads "## Deploying on **Choreo**" and
must be updated to use the requested platform name; change that heading text to
"## Deploying on **WSO2 Integration Platform**" (update any other occurrences of
"Choreo" in the README to "WSO2 Integration Platform" to keep terminology
consistent).
- Line 134: The README's troubleshooting line "Check OAuth token validity and
refresh token" references OAuth credentials that don't exist in config.bal;
either add the missing OAuth keys (e.g., client_id, client_secret,
refresh_token, access_token) to config.bal or update the README.md
troubleshooting section to reference the actual authentication method and config
keys used by the project (modify the line in README.md or the section around
it), and ensure consistency between config.bal and README.md so the guidance is
actionable.
- Around line 104-112: The README's deployment steps currently reference
Choreo-specific concepts; replace that bulleted section with WSO2 Integration
Platform deployment instructions: describe signing in to WSO2 Integration Studio
or Management Console, importing this repository as an Integration Project,
configuring connectors (Salesforce/DocuSign) and required environment variables,
building and deploying to the WSO2 Micro Integrator or Integration Cloud
runtime, and monitoring logs/metrics via the Management Console; ensure the
updated steps mention where to set env vars for production and how to promote
the integration in the WSO2 platform (replace the Choreo terms "Integration",
"Technology", and "Type" with WSO2-specific workflow).
---
Duplicate comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md`:
- Around line 114-127: Remove the entire "Running Locally" section (the "##
Running Locally" header and its numbered steps) and any references to a
gitignored Config.toml or the local command "bal run" from README.md so the file
no longer instructs users to run the integration locally or points to a
non-existent Config.toml; ensure you also remove the duplicate_comment marker
and any duplicated guidance elsewhere in the README to avoid reintroducing the
same content.
---
Nitpick comments:
In `@ballerina-integrator/salesforce-closewon-contract-automation/README.md`:
- Line 39: Update the heading "Docusign Setup" in the README to use the correct
brand capitalization "DocuSign Setup" and scan the README for any other
occurrences of "Docusign" to replace them with "DocuSign" to ensure consistent
branding throughout.
- Around line 9-19: Condense the README's detailed 10-item feature list into 3–5
high-level bullets by grouping related actions: one bullet for event listening
and business validation (Change Data Capture + "Closed Won" & deal value
checks), one for data retrieval and template selection (contact lookup by signer
role + DocuSign template choice), one for envelope creation (pre-filled fields +
configured signer(s) + CC recipients + custom subject/routing), and one for
post-send actions and robustness (update Opportunity stage to "Contract Sent" +
error handling/logging); update the existing bullet list under the feature
summary to replace the 10 bullets with these grouped items so the README remains
concise and focused.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 59c077dc-2460-4aa3-945b-82f125fdaedb
📒 Files selected for processing (1)
ballerina-integrator/salesforce-closewon-contract-automation/README.md
|
Prebuilt Integration Checklist
|
…me/password to OAuth2 and update related configurations.
…er to use the service path for channel specification, with corresponding documentation updates.
…geEventHeader.recordIds` instead of `entityId`.
…s Salesforce integration functions.
… JSON objects and arrays.
…stead of an array of `recordIds`.
…roved data handling.
…fely extract `ContactId` via JSON conversion with explicit error handling.
…c, adding robust error handling and configuration validation, and updating README documentation with detailed setup and troubleshooting.
…ing for `ENVELOPE_IS_INCOMPLETE` by adding detailed README instructions and in-code logging.
|
Shall we use refresh token flow for docusign and salesforce |
…leshooting details in the README.
There was a problem hiding this comment.
Pull request overview
Adds a new Ballerina integration package intended to automate DocuSign contract sending when Salesforce Opportunities transition to “Closed Won”, along with Choreo deployment assets and repository registration for CI/project discovery.
Changes:
- Introduces a new
salesforce-closewon-contract-automationintegration package (listener + envelope creation flow + mappings/types/config). - Adds Choreo artifacts (config schema, instructions, diagram) and end-user documentation (README).
- Registers the new integration path in
.github/workflows/projects.json.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| ballerina-integrator/salesforce-closewon-contract-automation/types.bal | Defines Salesforce/DocuSign-related record types and configuration records. |
| ballerina-integrator/salesforce-closewon-contract-automation/main.bal | Salesforce CDC listener service entrypoint for change events. |
| ballerina-integrator/salesforce-closewon-contract-automation/functions.bal | Salesforce query helpers, template selection, dispatch criteria, and stage update stub. |
| ballerina-integrator/salesforce-closewon-contract-automation/data_mappings.bal | Mapping + validation utilities for envelope subject and signer details. |
| ballerina-integrator/salesforce-closewon-contract-automation/connections.bal | Initializes Salesforce/DocuSign clients and Salesforce listener. |
| ballerina-integrator/salesforce-closewon-contract-automation/config.bal | Declares configurable records for Salesforce/DocuSign/templates/business rules. |
| ballerina-integrator/salesforce-closewon-contract-automation/automation.bal | Core orchestration: validate, select signer/template, create & send envelope. |
| ballerina-integrator/salesforce-closewon-contract-automation/agents.bal | Placeholder scaffolding for future AI-powered logic. |
| ballerina-integrator/salesforce-closewon-contract-automation/README.md | Setup, configuration, deployment and troubleshooting documentation. |
| ballerina-integrator/salesforce-closewon-contract-automation/Ballerina.toml | Package metadata for the new integration. |
| ballerina-integrator/salesforce-closewon-contract-automation/.gitignore | Ignores build artifacts and local config. |
| ballerina-integrator/salesforce-closewon-contract-automation/.choreo/instructions.md | Choreo-facing deployment/setup instructions. |
| ballerina-integrator/salesforce-closewon-contract-automation/.choreo/diagram.md | Process diagram for the integration flow. |
| ballerina-integrator/salesforce-closewon-contract-automation/.choreo/config-schema.json | Choreo configuration schema for deployment-time config UI/validation. |
| .github/workflows/projects.json | Adds the new integration path to the projects list. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
Co-authored-by: Haritha Hasathcharu <42366642+hasathcharu@users.noreply.github.com>
Shall we fix these |
Shall we fix the unchecked |
…dd Dependencies.toml
…EADME.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…unctions.bal Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
Prebuilt Integration Checklist
|
Fixes: https://github.com/wso2-enterprise/integration-engineering/issues/71
Summary by CodeRabbit
New Features
Documentation