Skip to content

Conversation

@michelle0927
Copy link
Collaborator

@michelle0927 michelle0927 commented Oct 27, 2025

Resolves #18820

Summary by CodeRabbit

Release Notes

  • New Features

    • Added event triggers for Opportunity Contact Changed, Opportunity Marked Won or Lost, Opportunity Ownership Changed, and Opportunity Reopened
    • Added new activity tracking capability to monitor tasks and activities for specific opportunities
  • Chores

    • Version updates to multiple actions and sources for improved stability and maintenance
@vercel
Copy link

vercel bot commented Oct 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
pipedream-docs Ignored Ignored Oct 27, 2025 6:41pm
pipedream-docs-redirect-do-not-edit Ignored Ignored Oct 27, 2025 6:41pm
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 27, 2025

Walkthrough

Adds five new Microsoft Dynamics 365 Sales opportunity-level event sources for ownership changes, won/lost status, reopening, contact changes, and activity logging. Enhances the core app module with activity pointer API and opportunity ID property definitions. Version bumps applied to package, actions, and existing sources.

Changes

Cohort / File(s) Summary
Version Bumps
components/microsoft_dynamics_365_sales/actions/create-custom-entity/create-custom-entity.mjs, components/microsoft_dynamics_365_sales/actions/find-contact/find-contact.mjs
Bumped action metadata versions from 0.0.4 to 0.0.5
Package and Source Version Updates
components/microsoft_dynamics_365_sales/package.json, components/microsoft_dynamics_365_sales/sources/new-opportunity-created/new-opportunity-created.mjs, components/microsoft_dynamics_365_sales/sources/opportunity-close-date-updated/opportunity-close-date-updated.mjs, components/microsoft_dynamics_365_sales/sources/opportunity-close-probability-updated/opportunity-close-probability-updated.mjs, components/microsoft_dynamics_365_sales/sources/opportunity-estimated-value-updated/opportunity-estimated-value-updated.mjs, components/microsoft_dynamics_365_sales/sources/opportunity-stage-updated/opportunity-stage-updated.mjs
Updated package version from 0.2.0 to 0.3.0; bumped existing source versions from 0.0.1 to 0.0.2
Core App Module Enhancement
components/microsoft_dynamics_365_sales/microsoft_dynamics_365_sales.app.mjs
Added opportunityId prop definition with async options function fetching opportunities; added listActivityPointers(opts) method for activity pointer API endpoint
New Activity Source
components/microsoft_dynamics_365_sales/sources/new-opportunity-activity/new-opportunity-activity.mjs
New source emitting events when tasks, meetings, or emails are logged on an opportunity; filters activities by opportunityId with metadata generation from activity creation timestamp
New State Tracking Sources with Contact/Ownership Change Detection
components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs, components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs
New sources tracking per-opportunity contact and ownership IDs in persistent storage; emit events when changes detected via comparison of _parentcontactid_value and _ownerid_value against stored mappings
New Status Change Sources
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs, components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs
New sources tracking opportunity state codes; emit events when state transitions to won (1), lost (2), or reopened (0); maintain per-opportunity state history for change detection

Sequence Diagram

sequenceDiagram participant Workflow as Workflow participant Source as State-Tracking Source participant API as Dynamics 365 API participant DB as Persistent DB Workflow->>Source: Poll/Trigger event check Source->>DB: Get stored state (contactIds/ownershipIds/stateCodes) Source->>API: listOpportunities (ordered by modifiedon desc) API-->>Source: Return opportunities Source->>Source: Compare current state vs stored state alt Change Detected Source->>DB: Update stored state mapping Source->>Source: Generate metadata (id, summary, ts) Source-->>Workflow: Emit event (changed opportunities) else No Change Source-->>Workflow: Emit nothing end 
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • State tracking logic review: Five new sources implement similar but distinct state comparison patterns (contact IDs, ownership IDs, state codes). Each requires separate verification of change detection logic, DB persistence, and filtering correctness.
  • API integration verification: Core app module additions (listActivityPointers, opportunityId prop) need validation for correct parameter construction and response mapping.
  • Metadata generation consistency: Ensure all new sources correctly construct unique IDs and summaries following established patterns.
  • Potential areas needing attention:
    • State comparison logic in opportunity-contact-changed.mjs, opportunity-ownership-changed.mjs, opportunity-marked-won-or-lost.mjs, opportunity-reopened.mjs to verify edge cases (null values, first run, state transitions)
    • listActivityPointers method options merging and endpoint correctness
    • opportunityId prop definition async options pagination handling via odata.nextLink

Possibly related PRs

  • Microsoft Dynamics - new sources #18849: Updates the same Microsoft Dynamics 365 Sales component with related action versions, core app enhancements, and source module additions; direct code-level overlap in component structure and metadata patterns.

Suggested reviewers

  • jcortes

Poem

🐰 Five new sources hop into place,
Tracking changes at Dynamics pace,
Ownership shifts, contacts align,
Opportunities won—the workflow will shine!
Activity pointers now point the way,
Fresh versions bring a brighter day! 🌟

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description provided is minimal, containing only "Resolves #18820" without addressing the required template structure. The repository template specifies a required "WHY" section to explain the rationale behind the changes, but this section is entirely missing from the description. While the issue reference provides context, the description does not follow the specified template format or provide substantive explanation of the changes.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The pull request title "Microsoft Dynamics - new sources" is clearly related to the main change in the changeset, which involves adding five new Microsoft Dynamics event sources for opportunity-level triggers. The title accurately describes the primary contribution without misleading information. While the title could be more specific about the nature of these sources (e.g., "opportunity triggers"), it is sufficiently descriptive to convey the essential change at a high level.
Linked Issues Check ✅ Passed The linked issue #18820 specifies five opportunity-level event sources to implement: opportunity ownership changed, opportunity marked as won or lost, opportunity reopened, new contact added to opportunity, and new task/meeting/email logged on opportunity. The raw summary confirms that all five sources have been successfully added as new modules: opportunity-ownership-changed, opportunity-marked-won-or-lost, opportunity-reopened, opportunity-contact-changed, and new-opportunity-activity. Supporting infrastructure was also added, including the opportunityId property definition and listActivityPointers method in the main app module, which enable the new sources' functionality. All requirements from the linked issue appear to be met.
Out of Scope Changes Check ✅ Passed The pull request changes consist primarily of five new opportunity-level event source modules that directly implement the requirements from linked issue #18820, along with supporting infrastructure (opportunityId property and listActivityPointers method) that enables their functionality. Version bumps across existing actions, sources, and the component package are maintenance-related metadata changes that do not introduce out-of-scope functionality. All changes are aligned with the stated objective of implementing opportunity-level triggers for Microsoft Dynamics workflows.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch issue-18820

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@michelle0927 michelle0927 marked this pull request as ready for review October 27, 2025 18:43
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (2)
components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (1)

34-34: Consider explicit object copy for clarity.

Currently newStateCodes references the same object as stateCodes when it exists. While this works correctly, using the spread operator makes the intent clearer.

- const newStateCodes = stateCodes || {}; + const newStateCodes = { ...(stateCodes || {}) };
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (1)

54-73: LGTM: State change detection logic is sound.

The getRelevantResults method correctly implements transition detection to Won/Lost states by:

  • Storing previous state codes per opportunity
  • Emitting only when an opportunity transitions into a monitored state
  • Avoiding false positives on initial deployment

The logic properly handles edge cases like state cycling (Won → Open → Won) by re-emitting on each transition to a monitored state.

Consider adding inline comments to clarify the state tracking logic, especially around line 62-68 where the condition checks for state transitions:

 for (const result of results) { + // Emit event if: (1) we have prior state, (2) state changed, (3) new state is monitored if (stateCodes && (stateCodes[result.opportunityid] !== result.statecode && this.stateCodes.includes(result.statecode) ) ) { relevantResults.push(result); } + // Always update stored state for this opportunity newStateCodes[result.opportunityid] = result.statecode; }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 134b7b4 and 8dfeb3a.

📒 Files selected for processing (14)
  • components/microsoft_dynamics_365_sales/actions/create-custom-entity/create-custom-entity.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/actions/find-contact/find-contact.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/microsoft_dynamics_365_sales.app.mjs (2 hunks)
  • components/microsoft_dynamics_365_sales/package.json (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/new-opportunity-activity/new-opportunity-activity.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/new-opportunity-created/new-opportunity-created.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-close-date-updated/opportunity-close-date-updated.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-close-probability-updated/opportunity-close-probability-updated.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-estimated-value-updated/opportunity-estimated-value-updated.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (1 hunks)
  • components/microsoft_dynamics_365_sales/sources/opportunity-stage-updated/opportunity-stage-updated.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
components/microsoft_dynamics_365_sales/microsoft_dynamics_365_sales.app.mjs (1)
components/microsoft_dynamics_365_sales/actions/create-custom-entity/create-custom-entity.mjs (1)
  • response (153-156)
components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs (4)
components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs (2)
  • relevantResults (34-34)
  • ts (47-47)
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (2)
  • relevantResults (60-60)
  • ts (75-75)
components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (2)
  • relevantResults (36-36)
  • ts (51-51)
components/microsoft_dynamics_365_sales/sources/new-opportunity-activity/new-opportunity-activity.mjs (1)
  • ts (37-37)
components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs (4)
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (2)
  • relevantResults (60-60)
  • ts (75-75)
components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs (2)
  • relevantResults (34-34)
  • ts (47-47)
components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (2)
  • relevantResults (36-36)
  • ts (51-51)
components/microsoft_dynamics_365_sales/sources/new-opportunity-activity/new-opportunity-activity.mjs (1)
  • ts (37-37)
components/microsoft_dynamics_365_sales/sources/new-opportunity-activity/new-opportunity-activity.mjs (4)
components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs (1)
  • ts (47-47)
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (1)
  • ts (75-75)
components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs (1)
  • ts (47-47)
components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (1)
  • ts (51-51)
components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (3)
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (4)
  • stateCodes (58-58)
  • newStateCodes (59-59)
  • relevantResults (60-60)
  • ts (75-75)
components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs (2)
  • relevantResults (34-34)
  • ts (47-47)
components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs (2)
  • relevantResults (34-34)
  • ts (47-47)
components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (1)
components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (4)
  • stateCodes (33-33)
  • newStateCodes (34-34)
  • relevantResults (36-36)
  • ts (51-51)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Lint Code Base
  • GitHub Check: Publish TypeScript components
  • GitHub Check: Verify TypeScript components
🔇 Additional comments (26)
components/microsoft_dynamics_365_sales/sources/opportunity-estimated-value-updated/opportunity-estimated-value-updated.mjs (1)

8-8: Version bump is appropriate.

The version change from 0.0.1 to 0.0.2 aligns with the broader package versioning updates as part of this PR. The existing change-detection logic and state management are sound, and no functional changes are introduced here.

components/microsoft_dynamics_365_sales/sources/opportunity-stage-updated/opportunity-stage-updated.mjs (1)

8-8: Version bump looks good.

The version bump from 0.0.1 to 0.0.2 is consistent with the broader package versioning changes in this PR.

components/microsoft_dynamics_365_sales/sources/opportunity-close-probability-updated/opportunity-close-probability-updated.mjs (1)

8-8: Version bump looks good.

The version increment aligns with the broader package updates in this PR and introduces no functional changes.

components/microsoft_dynamics_365_sales/sources/opportunity-close-date-updated/opportunity-close-date-updated.mjs (1)

8-8: Clarify contradiction between "no functional changes" claim and version bump.

The original review states this file has "no functional, control-flow, or error-handling changes," yet the version was bumped from 0.0.1 to 0.0.2. This is inconsistent—patch version bumps typically indicate changes. Additionally, only 5 of 10 opportunity sources were bumped to 0.0.2 while others remain at 0.0.1, suggesting selective versioning.

Either remove the version bump if no changes were made, or clarify what changes warrant the bump and ensure the versioning strategy is consistently applied across all opportunity sources.

components/microsoft_dynamics_365_sales/sources/opportunity-reopened/opportunity-reopened.mjs (4)

1-10: LGTM! Module metadata is well-defined.

The module structure, naming, and dedupe strategy are appropriate for tracking opportunity reopen events.


11-18: LGTM! State persistence methods follow Pipedream conventions.

The getter/setter pattern for tracking state codes is clean and appropriate.


19-31: LGTM! Configuration methods are correctly implemented.

The resource function, query parameters, and timestamp field configuration are all appropriate for tracking opportunity modifications.


50-57: LGTM! Metadata generation is appropriate.

The composite ID using opportunityid and parsed timestamp ensures proper deduplication, and the summary format is clear and informative.

components/microsoft_dynamics_365_sales/sources/opportunity-contact-changed/opportunity-contact-changed.mjs (5)

1-2: LGTM!

Standard import pattern for extending the common base.


3-10: LGTM!

Module metadata follows Pipedream conventions and accurately describes the source's purpose.


13-18: LGTM!

Storage methods follow standard patterns for persisting state between polling cycles.


19-31: LGTM!

Resource configuration methods properly set up opportunity polling with appropriate ordering and timestamp tracking.


46-53: LGTM!

Metadata generation follows the established pattern from other opportunity sources, properly combining opportunity ID with timestamp for unique event identification.

components/microsoft_dynamics_365_sales/sources/opportunity-ownership-changed/opportunity-ownership-changed.mjs (4)

1-10: LGTM! Module definition follows the established pattern.

The import structure, key, name, description, version, type, and dedupe settings are appropriate for a new opportunity ownership change source.


13-18: LGTM! Standard persistence pattern.

The getter and setter methods for ownership IDs follow the established pattern seen in similar sources like opportunity-contact-changed.mjs.


19-31: LGTM! Resource configuration is correct.

The resource function, query arguments, and timestamp field configuration are appropriate and consistent with similar sources in the PR.


46-53: LGTM! Metadata generation follows the established pattern.

The unique ID construction and summary format are consistent with similar sources in the PR (opportunity-contact-changed.mjs line 46, opportunity-marked-won-or-lost.mjs line 74).

components/microsoft_dynamics_365_sales/package.json (1)

3-3: LGTM: Version bump aligns with new features.

The minor version increment from 0.2.0 to 0.3.0 appropriately reflects the addition of new opportunity-level event sources and API enhancements.

components/microsoft_dynamics_365_sales/actions/create-custom-entity/create-custom-entity.mjs (1)

9-9: LGTM: Metadata version bump.

Version update with no functional changes.

components/microsoft_dynamics_365_sales/actions/find-contact/find-contact.mjs (1)

7-7: LGTM: Metadata version bump.

Version update with no functional changes.

components/microsoft_dynamics_365_sales/sources/new-opportunity-created/new-opportunity-created.mjs (1)

8-8: LGTM: Metadata version bump.

Version update with no functional changes.

components/microsoft_dynamics_365_sales/microsoft_dynamics_365_sales.app.mjs (2)

36-56: LGTM: opportunityId prop follows established patterns.

The property definition correctly implements async options with pagination support, consistent with the existing contactId prop pattern.


116-121: LGTM: listActivityPointers method follows existing conventions.

The method implementation is consistent with other list methods (e.g., listOpportunities, listContacts) and properly integrates with the _makeRequest infrastructure.

components/microsoft_dynamics_365_sales/sources/new-opportunity-activity/new-opportunity-activity.mjs (1)

1-35: LGTM: Source structure and data retrieval logic.

The source correctly extends the common base, implements proper filtering using OData syntax for the opportunity relationship, and follows established patterns for ordering and timestamp handling.

components/microsoft_dynamics_365_sales/sources/opportunity-marked-won-or-lost/opportunity-marked-won-or-lost.mjs (2)

74-83: LGTM: Metadata generation correctly labels Won/Lost states.

The summary string appropriately reflects the state code (1=Won, 2=Lost) and includes the opportunity name for clear identification.


1-53: LGTM: Source configuration and base methods.

The source properly extends common patterns, provides appropriate state code options for Won (1) and Lost (2), and implements correct resource retrieval and timestamp handling.

Copy link
Collaborator

@GTFalcao GTFalcao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@vunguyenhung vunguyenhung merged commit 7030774 into master Oct 28, 2025
10 checks passed
@vunguyenhung vunguyenhung deleted the issue-18820 branch October 28, 2025 04:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants