Skip to main content
Quartyl
Reportsprofessional

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.

Quartyl Team

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_OFF or ARCHIVED. Anything earlier (DRAFT, STUDY_INITIALIZED, PROCESSING) has partial or stale results, and REJECTED / FAILED must be re-submitted first — either way the endpoint answers 409 with the current state named. Note what IN_REVIEW costs: a build requested there also records the approval and builds the workbook, so the study lands at DOCUMENT_GENERATED rather 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_data the 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

  1. The request. POST /api/v1/studies/{id}/final-document with 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.
  2. The job. A Job row is created for the generation — the file it will produce, named Transfer-Pricing Report-{entity}.docx — and the generate_final_document Celery 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.
  3. 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.parameters and Study.analysis_data merged 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.
  4. The two files. The finished .docx uploads to storage and its file id is stored on the study as report_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 as report_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 as pdf_error on the job’s summary and leaves report_pdf_file_id null. A null PDF means “no PDF available for this study”, not a failed generation.
  5. The approval leg (only at In Review). A study still at IN_REVIEW has no workbook, and REPORT_GENERATED is 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 as report_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.
  6. The completion. The job moves to completed with both file ids and filenames in its summary (report_docx_file_id, report_pdf_file_id when present, plus pdf_error if that leg failed or excel_error if 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_GENERATED when the run started under review (one audit row per leg), and the single REPORT_GENERATED → DOCUMENT_GENERATED step otherwise. A study already at DOCUMENT_GENERATED, SIGNED_OFF or ARCHIVED stays exactly where it is.
  7. 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_GENERATED advances the study to DOCUMENT_GENERATED, because that is the canonical meaning of the state. A build at IN_REVIEW advances two legs: the workbook that REPORT_GENERATED stands for is built in the same run, then the document step follows, so IN_REVIEW → REPORT_GENERATED → DOCUMENT_GENERATED each 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 at IN_REVIEW holding 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 at IN_REVIEW, with the reason on the job as excel_error: the state is never claimed for a file that does not exist. From DOCUMENT_GENERATED, SIGNED_OFF or ARCHIVED the 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

Book a Demo

Tell us what you'd like benchmarked

We'll confirm a 30-minute screen-share slot within one business day.

We reply within one business day. Your details are used only to arrange the demo — never shared or sold.