Skip to content

Add ability to search issues by crm organization

Lee Tickett requested to merge 2256-search-issues-by-crm-organization into master

What does this MR do and why?

Related to #2256

If you're new to customer relations/crm- take a quick glance at the docs for some background https://docs.gitlab.com/ee/user/crm/#customer-relations-management-crm

This MR adds crm organization filtering to the issue finder, in turn allowing querying by manipulating the querystring (e.g. we don't have a pretty UI/search filter bar widget thingy).

We also add a button to the crm organizations list to navigate directly to all group issues for that organiztion.

We have just merged the same functionality for crm contacts !75451 (merged) - so hopefully this will be plain sailing 🤞

Screenshots or screen recordings

issue_search_by_crm_organization

How to set up and validate locally

From rails console:
1. Enable feature flag:
Feature.enable(:customer_relations)
From GraphiQL (http://gdk.test:3000/-/graphql-explorer):
2. Pick a an issue (I used http://gdk.test:3000/flightjs/Flight/-/issues/30)
4. Create a few organizations for the group the issue belongs to:
mutation {
  customerRelationsOrganizationCreate(input:
    { 
      groupId: "gid://gitlab/Group/26" 
      name: "Some company inc"
    }) {
    organization {
      id
    }
    errors
  }
}
5. Create a few contacts for the group the issue belongs to (attaching them to the organizations you just created):
mutation {
  customerRelationsContactCreate(input:
    {
      groupId: "gid://gitlab/Group/26"
      firstName: "Lee"
      lastName: "Tickett"
      email: "example@gitlab.com"
      organizationId: "gid://gitlab/CustomerRelations::Organization/4"
    }) {
    contact {
      id
      firstName
      lastName
    }
    errors
  }
}
6. Attempt to add/remove those contacts from your issue (via graphql... or via `/add_contacts` quick action):
mutation {
  issueSetCrmContacts(input:
    {
      projectPath: "flightjs/Flight"
      iid: "30"
      operationMode: REPLACE
	contactIds: [
        "gid://gitlab/CustomerRelations::Contact/14",
        "gid://gitlab/CustomerRelations::Contact/12"
      ]
    }) {
    issue {
     id
      customerRelationsContacts {
        nodes {
          id
          firstName
          lastName
        }
      }
    }
    errors
  }
}
7. Visit the group organizations list http://gdk.test:3000/groups/flightjs/-/crm/organizations
8. Click the issues button for an organization and ensure the correct issues are returned

Database

Generated SQL

SELECT issues.* FROM issues WHERE EXISTS (SELECT "issue_customer_relations_contacts".* FROM "issue_customer_relations_contacts" INNER JOIN "customer_relations_contacts" "contact" ON "contact"."id" = "issue_customer_relations_contacts"."contact_id" WHERE "contact"."organization_id" = 4 AND (issue_id = issues.id))
Query plan
 Nested Loop  (cost=19.40..43.98 rows=7 width=1410) (actual time=0.058..0.059 rows=0 loops=1)
   Buffers: shared hit=5
   I/O Timings: read=0.000 write=0.000
   ->  HashAggregate  (cost=18.83..18.90 rows=7 width=8) (actual time=0.057..0.058 rows=0 loops=1)
         Group Key: issue_customer_relations_contacts.issue_id
         Buffers: shared hit=5
         I/O Timings: read=0.000 write=0.000
         ->  Nested Loop  (cost=0.30..18.82 rows=7 width=8) (actual time=0.021..0.021 rows=0 loops=1)
               Buffers: shared hit=5
               I/O Timings: read=0.000 write=0.000
               ->  Index Scan using index_customer_relations_contacts_on_organization_id on public.customer_relations_contacts contact  (cost=0.15..4.68 rows=2 width=8) (actual time=0.020..0.020 rows=0 loops=1)
                     Index Cond: (contact.organization_id = 4)
                     Buffers: shared hit=5
                     I/O Timings: read=0.000 write=0.000
               ->  Index Scan using index_issue_customer_relations_contacts_on_contact_id on public.issue_customer_relations_contacts  (cost=0.15..7.01 rows=6 width=16) (actual time=0.000..0.000 rows=0 loops=0)
                     Index Cond: (issue_customer_relations_contacts.contact_id = contact.id)
                     I/O Timings: read=0.000 write=0.000
   ->  Index Scan using issues_pkey on public.issues  (cost=0.56..3.58 rows=1 width=1410) (actual time=0.000..0.000 rows=0 loops=0)
         Index Cond: (issues.id = issue_customer_relations_contacts.issue_id)
         I/O Timings: read=0.000 write=0.000
Timing
         Time: 6.696 ms
         - planning: 6.523 ms
         - execution: 0.173 ms
           - I/O read: 0.000 ms
           - I/O write: 0.000 ms
       
       Shared buffers:
         - hits: 5 (~40.00 KiB) from the buffer pool
         - reads: 0 from the OS file cache, including disk I/O
         - dirtied: 0
         - writes: 0

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Lee Tickett

Merge request reports