fix: advance signing groups by step completion instead of send status

This commit is contained in:
David Nguyen
2026-08-04 18:43:49 +10:00
parent 83eb53fffb
commit 635332da2c
@@ -373,7 +373,6 @@ export const completeDocumentWithToken = async ({
name: true,
email: true,
role: true,
sendStatus: true,
},
where: {
envelopeId: envelope.id,
@@ -399,24 +398,26 @@ export const completeDocumentWithToken = async ({
});
if (envelope.documentMeta?.signingOrder === DocumentSigningOrder.SEQUENTIAL) {
// The active group: every pending recipient sharing the lowest pending
// signing order. Members already activated (sendStatus SENT) are group
// peers who were notified earlier — activating only fresh members means
// a mid-group completion is a no-op and a step transition activates the
// whole next group at once.
// The next group: every pending recipient sharing the lowest pending
// signing order. If the completing recipient's own step is still
// pending (a group peer has not signed yet), the flow does not advance —
// the remaining peers were already activated when their step unlocked.
const nextGroup = filterRecipientsInFirstSigningGroup(pendingRecipients);
const recipientsToActivate = nextGroup.filter((r) => r.sendStatus !== SendStatus.SENT);
const currentRecipientOrder = recipient.signingOrder ?? Number.MAX_SAFE_INTEGER;
const hasCompletedCurrentStep = nextGroup.every(
(pendingRecipient) => (pendingRecipient.signingOrder ?? Number.MAX_SAFE_INTEGER) > currentRecipientOrder,
);
if (nextGroup.length > 0 && hasCompletedCurrentStep) {
// Dictation only applies when advancing to a single-recipient step.
const canDictateNextSigner =
Boolean(nextSigner) &&
Boolean(envelope.documentMeta?.allowDictateNextSigner) &&
nextGroup.length === 1 &&
recipientsToActivate.length === 1;
Boolean(nextSigner) && Boolean(envelope.documentMeta?.allowDictateNextSigner) && nextGroup.length === 1;
await prisma.$transaction(async (tx) => {
if (canDictateNextSigner && nextSigner) {
const [nextRecipient] = recipientsToActivate;
const [nextRecipient] = nextGroup;
await tx.documentAuditLog.create({
data: createDocumentAuditLogData({
@@ -449,7 +450,7 @@ export const completeDocumentWithToken = async ({
});
}
for (const nextRecipient of recipientsToActivate) {
for (const nextRecipient of nextGroup) {
await tx.recipient.update({
where: { id: nextRecipient.id },
data: {
@@ -466,7 +467,7 @@ export const completeDocumentWithToken = async ({
}
});
for (const nextRecipient of recipientsToActivate) {
for (const nextRecipient of nextGroup) {
await jobs.triggerJob({
name: 'send.signing.requested.email',
payload: {
@@ -479,6 +480,7 @@ export const completeDocumentWithToken = async ({
}
}
}
}
const haveAllRecipientsSigned = await prisma.envelope.findFirst({
where: {