Scope sub-third-parties per parent
Replace the many-to-many junction table with a direct parent_third_party_id foreign key on third_parties. Each sub-third-party now belongs to exactly one parent, making duplicates across parents independent entities. Replace the firstLevel boolean with an integer level field (1 = direct, 2+ = parent level + 1) to support arbitrary nesting depth. Remove the createThirdPartyThirdPartyMapping and deleteThirdPartyThirdPartyMapping mutations, the CLI link/unlink commands, and the corresponding MCP tools. Creating a child third party now just requires passing parentThirdPartyId on the existing createThirdParty mutation. The frontend walks the parentThirdParty chain to build display names like "Name (Ancestor1/Ancestor2)" and shows clickable ancestor links on the detail page. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -22,8 +22,7 @@ import { graphql } from "relay-runtime";
|
||||
import type { ThirdPartyGraphCreateMutation } from "#/__generated__/core/ThirdPartyGraphCreateMutation.graphql";
|
||||
import type { ThirdPartyGraphDeleteMutation } from "#/__generated__/core/ThirdPartyGraphDeleteMutation.graphql";
|
||||
import type { ThirdPartyGraphSelectQuery } from "#/__generated__/core/ThirdPartyGraphSelectQuery.graphql";
|
||||
|
||||
import { useMutationWithToasts } from "../useMutationWithToasts";
|
||||
import { useMutationWithToasts } from "#/hooks/useMutationWithToasts";
|
||||
|
||||
/* eslint-disable relay/unused-fields, relay/must-colocate-fragment-spreads */
|
||||
|
||||
@@ -51,14 +50,10 @@ const createThirdPartyMutation = graphql`
|
||||
|
||||
export function useCreateThirdPartyMutation() {
|
||||
const { __ } = useTranslate();
|
||||
|
||||
return useMutationWithToasts<ThirdPartyGraphCreateMutation>(
|
||||
createThirdPartyMutation,
|
||||
{
|
||||
successMessage: __("Third party created successfully."),
|
||||
errorMessage: __("Failed to create third party"),
|
||||
},
|
||||
);
|
||||
return useMutationWithToasts<ThirdPartyGraphCreateMutation>(createThirdPartyMutation, {
|
||||
successMessage: __("Third party created successfully"),
|
||||
errorMessage: __("Failed to create third party"),
|
||||
});
|
||||
}
|
||||
|
||||
const deleteThirdPartyMutation = graphql`
|
||||
@@ -138,7 +133,7 @@ export const paginatedThirdPartiesFragment = graphql`
|
||||
after: { type: "CursorKey", defaultValue: null }
|
||||
before: { type: "CursorKey", defaultValue: null }
|
||||
last: { type: "Int", defaultValue: null }
|
||||
filter: { type: "ThirdPartyFilter", defaultValue: { firstLevel: true } }
|
||||
filter: { type: "ThirdPartyFilter", defaultValue: { level: 1 } }
|
||||
) {
|
||||
thirdParties(
|
||||
first: $first
|
||||
@@ -154,6 +149,7 @@ export const paginatedThirdPartiesFragment = graphql`
|
||||
id
|
||||
name
|
||||
websiteUrl
|
||||
level
|
||||
updatedAt
|
||||
riskAssessments(
|
||||
first: 1
|
||||
@@ -184,7 +180,11 @@ export const thirdPartyNodeQuery = graphql`
|
||||
... on ThirdParty {
|
||||
name
|
||||
websiteUrl
|
||||
firstLevel
|
||||
level
|
||||
ancestors {
|
||||
id
|
||||
name
|
||||
}
|
||||
vettingStatus
|
||||
canVet: permission(action: "core:thirdParty:vet")
|
||||
canUpdate: permission(action: "core:thirdParty:update")
|
||||
@@ -229,14 +229,13 @@ export const thirdPartiesSelectQuery = graphql`
|
||||
thirdParties(
|
||||
first: 100
|
||||
orderBy: { direction: ASC, field: NAME }
|
||||
filter: { firstLevel: true }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
websiteUrl
|
||||
firstLevel
|
||||
level
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user