Skip to content

feat(condo): DOMA-13022 add subscription field into FindOrganizationsByAddress#7315

Open
Alexander-Turkin wants to merge 5 commits intomainfrom
feat/condo/DOMA-13022/add-subsctiprion-field
Open

feat(condo): DOMA-13022 add subscription field into FindOrganizationsByAddress#7315
Alexander-Turkin wants to merge 5 commits intomainfrom
feat/condo/DOMA-13022/add-subsctiprion-field

Conversation

@Alexander-Turkin
Copy link
Contributor

@Alexander-Turkin Alexander-Turkin commented Mar 5, 2026

Summary by CodeRabbit

  • New Features

    • Address-based organization search now includes subscription details: service end dates, active subscription ID and end date, and per-app subscription entries.
  • Tests

    • Added tests to verify subscription payload is present and correctly populated (including null values) in organization search results.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 5, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 151a5931-da7b-412c-81b0-001495c2cca5

📥 Commits

Reviewing files that changed from the base of the PR and between 8f3dcd1 and 11b1667.

📒 Files selected for processing (2)
  • apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js
  • apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js
  • apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js

📝 Walkthrough

Walkthrough

Adds organization subscription data to resident-domain lookups by extending GraphQL selection and types, resolving subscription via imported subscription field in the service, attaching subscription to finder return objects, and adding tests for subscription endAt propagation.

Changes

Cohort / File(s) Summary
GraphQL selection
apps/condo/domains/resident/gql.js
Extended FIND_ORGANIZATIONS_BY_ADDRESS_QUERY to include nested subscription fields (paymentsEndAt, metersEndAt, ticketsEndAt, newsEndAt, marketplaceEndAt, supportEndAt, aiEndAt, customizationEndAt, propertiesEndAt, analyticsEndAt, b2bApps { id endAt }, b2cApps { id endAt }, activeSubscriptionContextId, activeSubscriptionEndAt).
Service & runtime resolution
apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js
Imported ORGANIZATION_SUBSCRIPTION_FIELD, extended FindOrganizationByAddressOutput with subscription: OrganizationSubscriptionFeatures, resolved subscription data for each organization and used enriched organizations downstream.
Finder utilities
apps/condo/domains/resident/utils/serverSchema/findOrganizationsByAddress.js
Three finder functions now include subscription on returned organization objects (`subscription: organization.subscription
Schema declarations
apps/condo/schema.graphql, apps/condo/schema.ts
Added subscription: OrganizationSubscriptionFeatures to FindOrganizationByAddressOutput in GraphQL schema and corresponding TypeScript types.
Tests
apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js
Added tests (using dayjs and subscription test utilities) that verify subscription fields and endAt propagation when subscription contexts exist and when none exist.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant GQL as GraphQL Resolver
  participant Service as FindOrganizationsByAddressService
  participant Finder as Finder Utilities
  participant SubField as OrganizationSubscriptionFieldResolver
  participant DB as Database

  Client->>GQL: query FIND_ORGANIZATIONS_BY_ADDRESS
  GQL->>Service: handle request
  Service->>Finder: fetch organizations (address key variants)
  Finder->>DB: read organization records
  DB-->>Finder: organization records (include subscription id)
  Finder-->>Service: organizations (+subscription placeholder)
  Service->>SubField: resolve ORGANIZATION_SUBSCRIPTION_FIELD per org
  SubField->>DB: read subscription contexts/plans
  DB-->>SubField: subscription data (endAt, apps, contextId)
  SubField-->>Service: resolved subscription objects
  Service-->>GQL: enriched organizations with subscription
  GQL-->>Client: response with organizations.subscription
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through queries, quick and bright,
Brought subscriptions into the light.
EndAts, contexts — all in view,
Each org now wears a badge brand new. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a subscription field to the FindOrganizationsByAddress query/service, which is reflected across all modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/condo/DOMA-13022/add-subsctiprion-field

Warning

Tools execution failed with the following error:

Failed to run tools: Ping-pong health check failed


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.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dbdd4722ac

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +114 to +117
const organizationsWithSubscription = await Promise.all(
organizations.map(async (organization) => {
const subscription = await ORGANIZATION_SUBSCRIPTION_FIELD.resolver(organization, {}, context)
return { ...organization, subscription }

Choose a reason for hiding this comment

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

P2 Badge Defer subscription hydration until after org filtering

This eagerly calls ORGANIZATION_SUBSCRIPTION_FIELD.resolver for every candidate organization before fetchOrganizationData applies its final filtering, so organizations that are later dropped (for example in the tin && accountNumber branch) still incur full subscription computation. That resolver performs several DB reads (SubscriptionPlan/SubscriptionContext lookups and app-expiration plan loading), so this introduces avoidable N+1 query load and latency for high-density addresses; it should be moved after final eligibility is known (or batched/cached) to avoid production slowdowns.

Useful? React with 👍 / 👎.

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.

🧹 Nitpick comments (4)
apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js (3)

947-947: Test name is misleading relative to its assertions.

The test title says “null subscription”, but it asserts a defined subscription object with null fields. Consider renaming for clarity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js`
at line 947, Rename the test title string for the test starting with
test('Should return organization with null subscription when no contexts exist'
so it accurately describes the assertion (the response includes a defined
subscription object whose fields are null, not a null subscription). For example
update the title to "Should return organization with subscription object whose
fields are null when no contexts exist" (or similar) in the test declaration to
match the asserted behavior in the test.

905-968: Add a test case for multiple active subscription contexts.

Current coverage checks only single-context and no-context scenarios. Please add a case with two active paid contexts for the same organization to lock in expected merge/selection behavior in this API response.

Based on learnings: In apps/condo/domains/subscription/schema/ActivateSubscriptionPlanService.js, organizations can have multiple active paid subscription contexts at the same time for the same or different subscription plans. There should be no guard preventing duplicate active paid subscriptions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js`
around lines 905 - 968, Add a new test in the same suite that creates two active
paid subscription contexts for the same organization (use
createTestSubscriptionPlan and createTestSubscriptionContext with isTrial: false
and different endAt values), call findOrganizationsByAddressByTestClient and
locate the org by utils.organization.id; then assert that found.subscription is
defined, found.subscription.activeSubscriptionContextId is one of the created
context IDs and found.subscription.activeSubscriptionEndAt equals the later
endAt (max of the two), and other per-feature endAt fields reflect the expected
merged/selected values; reference TestUtils, createTestSubscriptionPlan,
createTestSubscriptionContext, findOrganizationsByAddressByTestClient and
utils.organization when adding the test.

935-944: Assert the full subscription contract that this endpoint now exposes.

The new query/service shape includes additional fields (e.g., customizationEndAt, propertiesEndAt, analyticsEndAt, b2bApps, b2cApps) that are not asserted yet. Adding explicit checks here will better protect the API contract from regressions.

Also applies to: 964-967

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js`
around lines 935 - 944, Update the test assertions in
FindOrganizationsByAddressService.test.js to cover the full subscription
contract returned by the service: add explicit expects on found.subscription for
customizationEndAt, propertiesEndAt, analyticsEndAt, b2bApps and b2cApps (and
mirror the same checks at the other assertion block referenced around lines
964-967); assert each new field against the expected value (e.g., endAt or null
as appropriate for the test scenario) and ensure
activeSubscriptionContextId/activeSubscriptionEndAt and existing fields remain
asserted.
apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js (1)

114-119: Consider avoiding eager per-organization subscription resolution.

This adds extra async work for every organization before final response mapping. If this endpoint can return many organizations, consider batching/caching subscription resolution (or resolving lazily only when requested) to reduce query pressure.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js`
around lines 114 - 119, The current Promise.all over organizations calling
ORGANIZATION_SUBSCRIPTION_FIELD.resolver for each organization (in
organizationsWithSubscription) eagerly issues a resolver per org and can create
high query load; replace this with a batched or cached approach: collect
organization IDs from organizations, call a single batch fetch (or use a
DataLoader from context) to retrieve all subscriptions in one query (e.g.,
getSubscriptionsForOrganizationIds or
context.loaders.organizationSubscription.loadMany), then map the returned
subscriptions back to organizations to produce the same { ...organization,
subscription } shape; alternatively resolve subscription lazily only when
requested by downstream resolvers rather than pre-resolving in
organizationsWithSubscription.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js`:
- Around line 114-119: The current Promise.all over organizations calling
ORGANIZATION_SUBSCRIPTION_FIELD.resolver for each organization (in
organizationsWithSubscription) eagerly issues a resolver per org and can create
high query load; replace this with a batched or cached approach: collect
organization IDs from organizations, call a single batch fetch (or use a
DataLoader from context) to retrieve all subscriptions in one query (e.g.,
getSubscriptionsForOrganizationIds or
context.loaders.organizationSubscription.loadMany), then map the returned
subscriptions back to organizations to produce the same { ...organization,
subscription } shape; alternatively resolve subscription lazily only when
requested by downstream resolvers rather than pre-resolving in
organizationsWithSubscription.

In
`@apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js`:
- Line 947: Rename the test title string for the test starting with test('Should
return organization with null subscription when no contexts exist' so it
accurately describes the assertion (the response includes a defined subscription
object whose fields are null, not a null subscription). For example update the
title to "Should return organization with subscription object whose fields are
null when no contexts exist" (or similar) in the test declaration to match the
asserted behavior in the test.
- Around line 905-968: Add a new test in the same suite that creates two active
paid subscription contexts for the same organization (use
createTestSubscriptionPlan and createTestSubscriptionContext with isTrial: false
and different endAt values), call findOrganizationsByAddressByTestClient and
locate the org by utils.organization.id; then assert that found.subscription is
defined, found.subscription.activeSubscriptionContextId is one of the created
context IDs and found.subscription.activeSubscriptionEndAt equals the later
endAt (max of the two), and other per-feature endAt fields reflect the expected
merged/selected values; reference TestUtils, createTestSubscriptionPlan,
createTestSubscriptionContext, findOrganizationsByAddressByTestClient and
utils.organization when adding the test.
- Around line 935-944: Update the test assertions in
FindOrganizationsByAddressService.test.js to cover the full subscription
contract returned by the service: add explicit expects on found.subscription for
customizationEndAt, propertiesEndAt, analyticsEndAt, b2bApps and b2cApps (and
mirror the same checks at the other assertion block referenced around lines
964-967); assert each new field against the expected value (e.g., endAt or null
as appropriate for the test scenario) and ensure
activeSubscriptionContextId/activeSubscriptionEndAt and existing fields remain
asserted.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9bd873b5-a5e5-4644-a83f-60e1a46464e8

📥 Commits

Reviewing files that changed from the base of the PR and between 3f10778 and dbdd472.

📒 Files selected for processing (4)
  • apps/condo/domains/resident/gql.js
  • apps/condo/domains/resident/schema/FindOrganizationsByAddressService.js
  • apps/condo/domains/resident/schema/FindOrganizationsByAddressService.test.js
  • apps/condo/domains/resident/utils/serverSchema/findOrganizationsByAddress.js

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

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.

🧹 Nitpick comments (1)
apps/condo/schema.ts (1)

29344-29344: Tighten subscription nullability to match resolver behavior

At Line 29344, subscription?: Maybe<OrganizationSubscriptionFeatures> is wider than runtime behavior: the resolver path shown in apps/condo/domains/organization/schema/fields/subscription.js:262-326 and :51-77 always returns a subscription object. Consider making this field non-null in GraphQL (OrganizationSubscriptionFeatures!) and regenerating this type so clients don’t carry unnecessary null checks.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/condo/schema.ts` at line 29344, The GraphQL schema's Organization type
declares subscription?: Maybe<OrganizationSubscriptionFeatures> but the resolver
for the subscription field always returns a non-null object; change the schema
so the subscription field is non-null (OrganizationSubscriptionFeatures!) and
regenerate the GraphQL types; update the declaration where "subscription" is
defined to remove the Maybe/optional, ensure the server schema and generated
client types are in sync, and run the codegen/regeneration step that produces
the updated types so clients no longer treat subscription as nullable.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@apps/condo/schema.ts`:
- Line 29344: The GraphQL schema's Organization type declares subscription?:
Maybe<OrganizationSubscriptionFeatures> but the resolver for the subscription
field always returns a non-null object; change the schema so the subscription
field is non-null (OrganizationSubscriptionFeatures!) and regenerate the GraphQL
types; update the declaration where "subscription" is defined to remove the
Maybe/optional, ensure the server schema and generated client types are in sync,
and run the codegen/regeneration step that produces the updated types so clients
no longer treat subscription as nullable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b81f5854-9794-46b9-9be9-63647579a7cc

📥 Commits

Reviewing files that changed from the base of the PR and between dbdd472 and 8f3dcd1.

📒 Files selected for processing (2)
  • apps/condo/schema.graphql
  • apps/condo/schema.ts

Here, we should have all the necessary data.
*/

const organizationsWithSubscription = await Promise.all(
Copy link
Member

Choose a reason for hiding this comment

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

You should at least add a commentary why do you resolve the field manually

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can't get a virtual field with find()

}

const result = await Promise.all(organizations.map(fetchOrganizationData))
const result = await Promise.all(organizationsWithSubscription.map(fetchOrganizationData))
Copy link
Member

Choose a reason for hiding this comment

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

It is a bit stragne that getting subscription is done not in a similar way

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 6, 2026

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants