Generating the Final Document: On-Demand Engagement Details
On-demand final document generation: the partner popup, the engagement details and narrative overrides, the job, the Word and PDF legs, and what the run does to the study state.
The Word master report is
generated on demand, never inside the analysis pipeline. A study’s
workflow — review, sign-off, archiving — runs on its own clock; the document
is built whenever the sign-off authority needs it, from the study’s settled
record. Building it writes the resulting files onto the study and advances the
workflow by exactly the legs whose deliverables now exist: a study at
REPORT_GENERATED takes the canonical step to DOCUMENT_GENERATED, and a
study still at IN_REVIEW takes that step plus the approval leg it
implies (see What the run does — and does not — change). From any later
state the workflow is left exactly where it was. This page is the flow: who
triggers it, what the popup collects, and what happens between clicking
Generate and the files being on the study.
Who can trigger it
- Roles. The final-document action is available to the Partner, the
Firm Admin and the platform-level Superadmin — the three roles on
the endpoint’s allow-list (
FINAL_DOCUMENT_ROLES). Every other role gets a 403; the action itself is the role boundary. - From where. The study’s results detail view: the Generate Final Document action opens the engagement popup for that study. The action is hidden while any generation job for that study is running, so the UI cannot stack two builds on one record. Once the study’s generation budget is spent (see The generation budget) the action stays visible and disabled, with the count printed on it — the budget is what stopped the study, and hiding the button would read as a permissions problem.
- The state gate. A formal seven-chapter document is only built from a
review-complete record:
IN_REVIEW,REPORT_GENERATED,DOCUMENT_GENERATED,SIGNED_OFForARCHIVED. Anything earlier (DRAFT,STUDY_INITIALIZED,PROCESSING) has partial or stale results, andREJECTED/FAILEDmust be re-submitted first — either way the endpoint answers 409 with the current state named. Note whatIN_REVIEWcosts: a build requested there also records the approval and builds the workbook, so the study lands atDOCUMENT_GENERATEDrather than staying under review (What the run does — and does not — change). - The data gate. The study must have persisted benchmarking results; with
no
analysis_datathe endpoint returns 409 (“run the analysis before generating a final document”). Report jobs share a dedicated queue, and a full one returns 429 rather than queuing behind the backlog. The sign-off workflow itself is in Partner sign-off; the document is the artifact that workflow produces, not a step in it.
The engagement popup
The benchmarking data itself is derived from the persisted study — the analysis data and the parameters. What the popup collects is the engagement identity the study cannot derive, injected into the report’s narrative slots and its cover:
| Field | Required | Where it lands |
|---|---|---|
| Prepared By | Yes | The cover’s “Prepared by”. A real field, not a defaulted one: the request rejects a blank value |
| Prepared For | No | The cover’s “Prepared for” (defaults to the tested party entity) |
| Report Date | No | The cover’s “Date of report”. Validated as a calendar date (YYYY-MM-DD, the date picker’s format); left blank it resolves to the day the build runs |
| Database Used | No | Chapter 5, the search narrative — the line renders only when supplied |
| Comparable Years | No | Chapter 1 (reporting period) and Chapter 5 — the line renders only when supplied |
| Regions Searched | No | Chapter 5, the search narrative — the line renders only when supplied |
| Purpose of Study | No | Chapter 1, section 1.1 (Taxpayer) — narrative override |
| Company Overview | No | Chapter 2, The Tested Party — narrative override |
| Transaction Description | No | Chapter 1, section 1.5 (Controlled Transactions) — narrative override |
| Functions, Assets and Risks | No | Chapter 4 — narrative override |
| Group Companies | No | Chapter 2, The Group — a table of entity / jurisdiction / relationship / business, up to 50 rows, each needing a name |
| Shareholding | No | Chapter 2, Shareholding Pattern — a table of shareholder / relationship / holding / jurisdiction, up to 50 rows, each needing a shareholder name; the same rows draw the ownership chart |
The four narrative fields are capped at 4,000 characters each — the same limit the API enforces — and the popup counts them live so a too-long narrative is caught while typing rather than by a rejected request.
Only Prepared By gates the submit; the rest are engagement detail. Leaving a narrative slot empty leaves the report’s deterministic fallback in place — the chapter is never blank — and leaving either schedule empty is its own statement: the chapter prints that the detail is not recorded in the study data rather than an empty table. A schedule row that names nobody is dropped before the request goes out, so an abandoned half-row cannot fail the whole generation.
What you type is kept as a per-study draft in the browser: close the popup mid-entry — deliberately or by accident — and the next open for that study restores it, with the dialog asking before discarding unsaved entries. The draft is cleared when a build is dispatched. It never leaves the device: it is not a server-side save, and another user on another machine will not see it.
What happens on submit
- The request.
POST /api/v1/studies/{id}/final-documentwith the popup payload. The endpoint checks the role (403), loads the study (404 if it does not exist), checks the state and the persisted results (409 for either), refuses a study whose generation budget is spent (409, naming the count), and refuses early if the report queue is full (429). The task is dispatched once the response has committed. - The job. A Job row is created for the generation — the file it will
produce, named
Transfer-Pricing Report-{entity}.docx— and thegenerate_final_documentCelery task is dispatched on the report queue, the queue that keeps document builds from wedging new analyses. No study mutation happens at request time: the job carries the progress, not the study. - The build. The task first checks the retention window on the study’s
raw dump (see The retention edge), then rebuilds the report context from
the persisted
Study.parametersandStudy.analysis_datamerged with the engagement fields and the narrative overrides. Two reconciliations happen here, both so the document matches the record a reviewer settled on: the accept/reject overrides recorded during review are applied to a build-only copy of the results, and the jurisdiction’s rules are resolved as of the financial year end, so a prior-year study is documented against the law in force then. The report engine then builds the report once — seven numbered chapters and twelve annexures as a single renderer-neutral content stream — and renders both files from that stream. Before either renderer runs, a consistency gate blocks a report that would contradict itself: a method the study’s own profit level indicator cannot compute, a conclusion at odds with the margin against the applied range, or an adjustment whose sign and stated direction disagree. The method/indicator check also runs at the endpoint, so an impossible document is refused before any job exists. It is all deterministic — no AI step. - The two files. The finished
.docxuploads to storage and its file id is stored on the study asreport_docx_file_id. Only then is the branded PDF built — from the same context, so the two deliverables cannot disagree on a number or on the range methodology — and stored asreport_pdf_file_id. The PDF leg is best-effort by design: the Word report is already safe by that point, so a PDF failure is recorded aspdf_erroron the job’s summary and leavesreport_pdf_file_idnull. A null PDF means “no PDF available for this study”, not a failed generation. - The approval leg (only at In Review). A study still at
IN_REVIEWhas no workbook, andREPORT_GENERATEDis the state that means one exists. So the same task builds the Excel workbook from the override-adjusted results, exactly as an approval would, and links it asreport_file_id. A study that already holds a workbook is not rebuilt — the state is satisfied by the file that is there, and the dump the workbook was built from may already be deleted. - The completion. The job moves to completed with both file ids and
filenames in its summary (
report_docx_file_id,report_pdf_file_idwhen present, pluspdf_errorif that leg failed orexcel_errorif the approval leg could not build the workbook); the UI polls the job (GET /api/v1/jobs/{id}) and surfaces the result. Each deliverable now on the study earns its state:IN_REVIEW→REPORT_GENERATED→DOCUMENT_GENERATEDwhen the run started under review (one audit row per leg), and the singleREPORT_GENERATED→DOCUMENT_GENERATEDstep otherwise. A study already atDOCUMENT_GENERATED,SIGNED_OFForARCHIVEDstays exactly where it is. - The failure. A failed build marks the job failed with the reason. The study’s state, its data and its previously generated files are untouched — the last good document stays the document of record until a generation replaces it.
What the run does — and does not — change
This is the design boundary that keeps the document useful.
- Each leg is recorded only when its deliverable exists. A build at
REPORT_GENERATEDadvances the study toDOCUMENT_GENERATED, because that is the canonical meaning of the state. A build atIN_REVIEWadvances two legs: the workbook thatREPORT_GENERATEDstands for is built in the same run, then the document step follows, soIN_REVIEW → REPORT_GENERATED → DOCUMENT_GENERATEDeach with their own audit row. That is deliberate — the roles allowed to request a client-facing master report are the roles allowed to approve the reviewed set, and leaving the study atIN_REVIEWholding a document would make Sign Off unreachable except by spending a second generation. If the workbook leg fails, the Word document is still stored and the study stays atIN_REVIEW, with the reason on the job asexcel_error: the state is never claimed for a file that does not exist. FromDOCUMENT_GENERATED,SIGNED_OFForARCHIVEDthe state does not move: no rollback to review, no re-approval, no reopening of anything. - Generation runs alongside the workflow. Review, overrides and sign-off continue while the document builds. The build takes no lock and records no review action — it writes file ids, the deliverables above, and the states those deliverables mean.
- Re-generation is safe. After sign-off — or after a correction to the engagement details — the document can be regenerated from the settled record without reopening the study. Each run stores new files and the study links the latest ids; those are the current documents of record.
- Two separate downloads. The Word and PDF files are downloaded independently, so a study whose PDF leg failed still serves its Word report: the UI says no PDF is available and offers regeneration, rather than failing the Word download with it.
- Contrast with the Excel workbook. The workbook is part of the workflow — report generation is a stage the study passes through when it is approved, and it stays the primary benchmarking deliverable. The Word (and PDF) document is a side channel: the same record, rendered into the narrative form, on the authority’s schedule.
The retention edge
The build works from the study’s persisted record plus its raw dump. If the
dump has passed the tenant’s retention window by the time the task runs,
the job fails with a clear DUMP_EXPIRED result rather than building a
degraded document — the remedy is to re-run the study (a fresh run captures
a fresh dump) and regenerate.
The generation budget
Each study gets five client-facing rebuilds, enforced at the one place that
creates the job — so a caller that read a stale counter cannot step around the
limit. The count comes from the job ledger rather than a column on the study:
the ledger is the record of what was dispatched, and a second counter would be
a second answer to the same question. It therefore includes builds that
failed. The study’s response carries both numbers
(report_generation_count, report_generation_limit) so the action can print
the figure the API enforces — 2/5 — instead of the frontend guessing it.
FAQ
Can I generate the document more than once? Yes, up to the study’s
generation budget — five builds. Each submission is a new job producing new
stored files, and the study’s file ids point at the latest generation, so
regenerate after correcting an engagement detail rather than editing the
document. The count is kept in the job ledger, not in a flag: it includes
builds that failed, because dispatching one is what spends it, and the action
prints the running total (2/5) so nothing is spent by surprise. When the
budget is gone the endpoint answers 409 and the files already produced stay
downloadable; raising the per-study limit is an administrator’s change.
Does generating the document change the study’s state? Not from the
endpoint, and only forward from the build: a study at REPORT_GENERATED moves
to DOCUMENT_GENERATED, and a study still at IN_REVIEW moves through the
approval leg first — the workbook is built in the same run — so it also lands
at DOCUMENT_GENERATED with both steps in the audit trail. Regenerating from
DOCUMENT_GENERATED, SIGNED_OFF or ARCHIVED changes nothing about the
state — only the linked files.
I generated a document and there is no PDF — did it fail? Check the job’s
summary. If report_docx_file_id is there and pdf_error is set, the Word
report built and stored correctly and the PDF leg alone failed; the job is
still completed, and the study simply has no PDF on it. Regenerate to try the
PDF again. The PDF is not a shortened report: it renders the same seven
chapters and the same Annexures A–L from the same content stream, so any
difference in length between the two files is typography, not omitted
analysis. See
Word and PDF: one document, two renderings.
Does the platform file the document anywhere? No. It builds, stores and links the deliverables for download; filing and submission are outside the platform.
The job failed — what should I check first? The job’s failure reason:
DUMP_EXPIRED means the retention window closed on the raw dump (re-run
the study); anything else is a generation fault to report, and the study
and its earlier reports are unaffected either way.
See it working in your workspace
Sign in to run the steps above on a real study — or book a demo and we will walk the workflow end to end.
Related docs
The Master Report: Seven Chapters and Twelve Annexures
How the Word master report is built: seven chapters, annexures A–L, the deterministic engine, the narrative slots, and the one content stream the PDF shares.
Read docThe Excel Workbook: Every Sheet Explained
The Excel workbook sheet by sheet: Strategy, Search Result, Accept Reject Matrix, Financial Results, Margin Analysis and Web Analysis, plus how the workbook is produced, stored and downloaded.
Read doc