Skip to content

Conversation

@MayaRainer
Copy link
Member

@MayaRainer MayaRainer commented Dec 24, 2025

As per internal discussion, PDFs generated when signing documents should contain a textual signature of both parties. This PR adds that.

image

@MayaRainer MayaRainer marked this pull request as ready for review December 25, 2025 16:44
Copy link
Member Author

@MayaRainer MayaRainer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ershad _a Could you have a look please? Here's a sample PDF:

Consulting agreement (19).pdf

head :created
end

def signed
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TRPC calls this endpoint to generate a PDF for the signed document.

@@ -0,0 +1,108 @@
<style>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have Tailwind in PDFs. Also note that webfonts don't seem to work in this context, so the default sans and cursive fonts are used. This happens in share certificates too:

Image

await documentsFactory.create({ companyId: company.id, text: "Test document text" });
const { user: recipient } = await usersFactory.create({ legalName: "Recipient 1" });
await companyContractorsFactory.create({ companyId: company.id, userId: recipient.id });
await companyContractorsFactory.create({ companyId: company.id, userId: recipient.id }, { withoutContract: true });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes the below cleaner as otherwise the user already has a contract.

.leftJoin(activeStorageBlobs, eq(activeStorageAttachments.blobId, activeStorageBlobs.id))
.where(where)
.orderBy(desc(documents.id));
.orderBy(desc(documents.id), desc(activeStorageAttachments.id));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To match document.live_attachment.


def active? = deactivated_at.nil?

def primary_admin = super || company_administrators.first
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Falling back to the current behaviour if the field isn't set.

@neetogit-bot neetogit-bot bot assigned ershad and unassigned ershad Dec 25, 2025
Copy link
Member

@ershad ershad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MayaRainer _a added a few comments, please take a look.

end

def signed
document = Document.find(params[:id])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be safe -

Suggested change
document = Document.find(params[:id])
document = Current.company.documents.find(params[:id])

Comment on lines +144 to +147
const response = await fetch(signed_company_document_url(ctx.company.externalId, document.documents.id), {
method: "POST",
headers: ctx.headers,
});
Copy link
Member

@ershad ershad Dec 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we make this API call, we are still inside the DB transaction, and the signedAt update hasn't been committed yet. Could be why I saw an empty field for contractor Date signed in the PDF when tested locally. But if the job is delayed for some reason, we won't see this issue. Could you please check? Ideally, we need to generate the doc outside the transaction.

t.jsonb "json_data", default: {"flags" => []}, null: false
t.boolean "equity_enabled", default: false, null: false
t.string "invite_link"
t.bigint "primary_admin_id"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to add this to frontend/db/schema.ts as well?


def active? = deactivated_at.nil?

def primary_admin = super || company_administrators.first
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent with the previous behavior:

Suggested change
def primary_admin = super || company_administrators.first
def primary_admin = super || company_administrators.order(:id).first

@neetogit-bot neetogit-bot bot assigned MayaRainer and unassigned ershad Dec 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants