Replies: 3 comments 2 replies
|
The best approach to this problem is:
The problem itself isn't difficult to solve with workflows as they're already mature enough for such use cases |
2 replies
|
I implemented a workflow for this one for anyone interested. Here's how it works:
export const main = async (params: {
opportunityId: string;
}): Promise<object> => {
const { opportunityId } = params;
if (!opportunityId) {
throw new Error("No Opportunity ID provided");
}
const dataGraphqlEndpoint = "https://YOUR_INSTANCE/graphql";
const twentyApiKey = "YOUR_API_KEY";
const query = `
query GetPreviousOpportunity($currentId: UUID!) {
opportunities(
filter: {
id: {
neq: $currentId
}
}
orderBy: {
createdAt: DescNullsLast
}
first: 1
) {
edges {
node {
id
name
createdAt
}
}
}
}
`;
const response = await fetch(dataGraphqlEndpoint, {
method: "POST",
headers: {
Authorization: `Bearer ${twentyApiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
variables: {
currentId: opportunityId,
},
}),
});
if (!response.ok) {
throw new Error(
`GraphQL request failed: ${response.status} ${response.statusText}`,
);
}
const result = await response.json();
if (result.errors?.length) {
throw new Error(
`GraphQL query failed: ${result.errors[0].message}`,
);
}
const previousOpportunity =
result.data?.opportunities?.edges?.[0]?.node;
// No previous Opportunity means this is the first one.
if (!previousOpportunity) {
return {
previousOpportunity: null,
nextName: "NO1001",
};
}
if (!previousOpportunity.name) {
throw new Error(
`Previous Opportunity ${previousOpportunity.id} has no name`,
);
}
// Expecting something like NO1000
// Customize this for your naming scheme
const match = previousOpportunity.name.match(/^NO(\d+)$/);
if (!match) {
throw new Error(
`Previous Opportunity name "${previousOpportunity.name}" is not in the expected NO#### format`,
);
}
const previousNumber = parseInt(match[1], 10);
const nextNumber = previousNumber + 1;
const nextName = `NO${nextNumber}`;
return {
previousNumber,
nextNumber,
nextName,
};
};
Having done this, I think this is too much to ask most people who just need a unique and incrementing Name for their opportunities. |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

Uh oh!
There was an error while loading. Please reload this page.
We are currently moving from Nutshell CRM to Twenty, and we ran into a gap that feels small on the surface but is very important in day-to-day operations.
In our current setup, every new lead/opportunity automatically receives the next sequential number. We use that number as our internal project number everywhere else across the business: quotes, folders, emails, file naming, job tracking, internal communication, and general reference. We are trying to avoid a process where employees manually assign project numbers, as it introduces mistakes, duplicates, skipped numbers, and inconsistent tracking.
Not having this functionality natively in Twenty is less than ideal, and we have yet to find a stable workaround.
Why this matters
For many teams, an opportunity often becomes the start of an internal job, project, or client file. A reliable sequential project number gives the business a shared reference that can be used across CRM, documents, accounting, operations, and production.
Without native support, teams are pushed toward:
Feature request
It would be extremely helpful to have a native field type or built-in automation for sequential numbering, for example:
Option 1: Auto-number field type
A dedicated field type, like:
Option 2: Object-level numbering rule
A setting on an object, such as Opportunities, that automatically assigns the next number when a new record is created.
Suggested capabilities
Ideally, this feature would support:
Why this would help
This is useful not only for sales. It can also support:
Many businesses need a simple, human-readable identifier generated automatically that can be referenced outside the CRM.
We would love to see Twenty support this, as it would remove significant friction and make the platform easier to adopt for operational teams, not just sales teams.
Thanks for considering it.
All reactions