diff --git a/app/finders/crm/contacts_finder.rb b/app/finders/crm/contacts_finder.rb index f7c2625f7886f3d4d201fedc238168a7d8d92b24..9babfd9bf05afc20926d6d1ad1502b0e9611c801 100644 --- a/app/finders/crm/contacts_finder.rb +++ b/app/finders/crm/contacts_finder.rb @@ -8,6 +8,7 @@ # group: Group, required # search: String, optional # state: CustomerRelations::ContactStateEnum, optional +# ids: int[], optional module Crm class ContactsFinder include Gitlab::Allowable @@ -24,6 +25,7 @@ def execute return CustomerRelations::Contact.none unless root_group contacts = root_group.contacts + contacts = by_ids(contacts) contacts = by_state(contacts) contacts = by_search(contacts) contacts.sort_by_name @@ -53,6 +55,12 @@ def by_state(contacts) contacts.search_by_state(params[:state]) end + def by_ids(contacts) + return contacts unless ids? + + contacts.search_by_ids(params[:ids]) + end + def search? params[:search].present? end @@ -60,5 +68,9 @@ def search? def state? params[:state].present? end + + def ids? + params[:ids].present? + end end end diff --git a/app/finders/crm/organizations_finder.rb b/app/finders/crm/organizations_finder.rb index 1a3df05aa11242122783c158e134a63471529210..ef317c338a83a9b5cac487a8cd0192f68d2f0a0c 100644 --- a/app/finders/crm/organizations_finder.rb +++ b/app/finders/crm/organizations_finder.rb @@ -8,6 +8,7 @@ # group: Group, required # search: String, optional # state: CustomerRelations::OrganizationStateEnum, optional +# ids: int[], optional module Crm class OrganizationsFinder include Gitlab::Allowable @@ -24,6 +25,7 @@ def execute return CustomerRelations::Organization.none unless root_group organizations = root_group.organizations + organizations = by_ids(organizations) organizations = by_search(organizations) organizations = by_state(organizations) organizations.sort_by_name @@ -53,6 +55,12 @@ def by_state(organizations) organizations.search_by_state(params[:state]) end + def by_ids(organizations) + return organizations unless ids? + + organizations.search_by_ids(params[:ids]) + end + def search? params[:search].present? end @@ -60,5 +68,9 @@ def search? def state? params[:state].present? end + + def ids? + params[:ids].present? + end end end diff --git a/app/graphql/resolvers/crm/contacts_resolver.rb b/app/graphql/resolvers/crm/contacts_resolver.rb index 9e23566965712e3bf95aabd504359df0deb26335..8cc2d3193378fba8e83b2320247f9756a23001b8 100644 --- a/app/graphql/resolvers/crm/contacts_resolver.rb +++ b/app/graphql/resolvers/crm/contacts_resolver.rb @@ -17,13 +17,25 @@ class ContactsResolver < BaseResolver required: false, description: 'State of the contacts to search for.' + argument :ids, [GraphQL::Types::ID], + required: false, + description: 'Filter contacts by IDs.' + def resolve(**args) + args[:ids] = parse_gids(args.delete(:ids)) + ::Crm::ContactsFinder.new(current_user, { group: group }.merge(args)).execute end def group object.respond_to?(:sync) ? object.sync : object end + + private + + def parse_gids(gids) + gids&.map { |gid| GitlabSchema.parse_gid(gid, expected_type: CustomerRelations::Contact).model_id } + end end end end diff --git a/app/graphql/resolvers/crm/organizations_resolver.rb b/app/graphql/resolvers/crm/organizations_resolver.rb index ef0c930a94abc42383eb511c2b6f642e0590bab5..277a6ae6e5ec5caa4083015054e8f46a4629eb4b 100644 --- a/app/graphql/resolvers/crm/organizations_resolver.rb +++ b/app/graphql/resolvers/crm/organizations_resolver.rb @@ -17,13 +17,25 @@ class OrganizationsResolver < BaseResolver required: false, description: 'State of the organization to search for.' + argument :ids, [GraphQL::Types::ID], + required: false, + description: 'Filter organizations by IDs.' + def resolve(**args) + args[:ids] = parse_gids(args.delete(:ids)) + ::Crm::OrganizationsFinder.new(current_user, { group: group }.merge(args)).execute end def group object.respond_to?(:sync) ? object.sync : object end + + private + + def parse_gids(gids) + gids&.map { |gid| GitlabSchema.parse_gid(gid, expected_type: CustomerRelations::Organization).model_id } + end end end end diff --git a/app/models/customer_relations/contact.rb b/app/models/customer_relations/contact.rb index ded6ab8687ae7a0e6d5195fa3975b854f7a818a6..185d57c80a987169864063f00836f05c0dff1e73 100644 --- a/app/models/customer_relations/contact.rb +++ b/app/models/customer_relations/contact.rb @@ -56,6 +56,10 @@ def self.search_by_state(state) where(state: state) end + def self.search_by_ids(ids) + where(id: ids) + end + def self.sort_by_name order("last_name ASC, first_name ASC") end diff --git a/app/models/customer_relations/organization.rb b/app/models/customer_relations/organization.rb index 705e84250c91741ea6ab67f089d7a4489d4a2a30..98fa6e609645a223a08b6e3f8fa66dc1e5b16014 100644 --- a/app/models/customer_relations/organization.rb +++ b/app/models/customer_relations/organization.rb @@ -38,6 +38,10 @@ def self.search_by_state(state) where(state: state) end + def self.search_by_ids(ids) + where(id: ids) + end + def self.sort_by_name order(name: :asc) end diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 109a738e6da6fdd449c80c386a3c8b72ecd9c979..094cf1c69941280bb34c7bb6b1a20e57a1753c73 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -11713,6 +11713,7 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="groupcontactsids"></a>`ids` | [`[ID!]`](#id) | Filter contacts by IDs. | | <a id="groupcontactssearch"></a>`search` | [`String`](#string) | Search term to find contacts with. | | <a id="groupcontactsstate"></a>`state` | [`CustomerRelationsContactState`](#customerrelationscontactstate) | State of the contacts to search for. | @@ -12069,6 +12070,7 @@ four standard [pagination arguments](#connection-pagination-arguments): | Name | Type | Description | | ---- | ---- | ----------- | +| <a id="grouporganizationsids"></a>`ids` | [`[ID!]`](#id) | Filter organizations by IDs. | | <a id="grouporganizationssearch"></a>`search` | [`String`](#string) | Search term used to find organizations with. | | <a id="grouporganizationsstate"></a>`state` | [`CustomerRelationsOrganizationState`](#customerrelationsorganizationstate) | State of the organization to search for. | diff --git a/spec/finders/crm/contacts_finder_spec.rb b/spec/finders/crm/contacts_finder_spec.rb index 14f838812a6056600ab9cf153864379ee6112a3e..c23e96bfe5a87abbf8ae1555e644a24fb8d81a25 100644 --- a/spec/finders/crm/contacts_finder_spec.rb +++ b/spec/finders/crm/contacts_finder_spec.rb @@ -143,6 +143,13 @@ expect(finder.execute).to match_array([search_test_b]) end end + + context 'when searching for contacts ids' do + it 'returns the expected contacts' do + finder = described_class.new(user, group: search_test_group, ids: [search_test_b.id]) + expect(finder.execute).to match_array([search_test_b]) + end + end end end end diff --git a/spec/finders/crm/organizations_finder_spec.rb b/spec/finders/crm/organizations_finder_spec.rb index 94b5d9e5874d2e5767240199a3eb92fc86be7ab8..926d4e7561f354013991d2e08063bc42c00c81e3 100644 --- a/spec/finders/crm/organizations_finder_spec.rb +++ b/spec/finders/crm/organizations_finder_spec.rb @@ -129,6 +129,13 @@ expect(finder.execute).to match_array([search_test_b]) end end + + context 'when searching for organizations ids' do + it 'returns the expected organizations' do + finder = described_class.new(user, group: search_test_group, ids: [search_test_a.id]) + expect(finder.execute).to match_array([search_test_a]) + end + end end end end diff --git a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb index eba26c8c71fb8e585843a899658f328cd058810c..94b743b7af85375d7893b0ac82775633992e99fb 100644 --- a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb +++ b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb @@ -77,6 +77,12 @@ expect(resolve_contacts(group, { state: :inactive })).to match_array([contact_a]) end end + + context 'when ids are provided' do + it 'returns the correct contacts' do + expect(resolve_contacts(group, { ids: [contact_a.to_global_id.to_s] })).to match_array([contact_a]) + end + end end end diff --git a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb index c80caf91f90ddb046cea28c53d0ac7549950c55a..0d49f640b1c2819007ddb671d3ca2938bc68aae1 100644 --- a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb +++ b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb @@ -71,6 +71,14 @@ expect(resolve_organizations(group, { state: :inactive })).to match_array([organization_a]) end end + + context 'when ids are provided' do + it 'returns the correct organizations' do + expect(resolve_organizations(group, { + ids: [organization_b.to_global_id.to_s] + })).to match_array([organization_b]) + end + end end end