Creating documents
$document = service('documents')->create( new IssueReceipt(), // a template, or its key: 'issue-receipt' $resource, // the resource of the owner record $person, // the owner record [ // the data of the view 'person' => ['uuid' => $uuid, 'name' => 'Ada Lovelace'], 'items' => $items, ], 'Issue receipt Ada Lovelace', // optional title; default: the title of the template);create() takes the template as object or as key (a string is a key, not
a class name).
The draft
Section titled “The draft”- The data is a snapshot: it is stored as JSON with the document;
later changes of the records do not change the document. It must be
encodable as JSON (scalars and arrays), otherwise an
InvalidArgumentException. - The owner is a record of a resource. The PDF becomes a file of that record and is downloaded with its permissions; it is not an ordinary attachment and cannot be deleted among the attachments.
- The content hash of the rendered HTML is stored; the signature will be bound to it.
document.createdis audited with the template, the owner and the content hash.
From an action
Section titled “From an action”Typically an action collects the data, creates the draft and starts the handover in one step:
Action::make('issue')->label('Issue')->icon('box-arrow-right') ->permission('receipts.manage') ->form(fn (Form $form, array|object $person): Form => $form->schema([...])) ->handle(function (array|object $person, array $data): string { $document = service('documents')->create(new IssueReceipt(), $this, $person, [ 'person' => ['uuid' => $this->recordUuid($person), 'name' => $person['title']], 'items' => $this->items($data), ]);
// The session is locked to the signing page until the employee enters their password. service('handover')->start($this->panel(), $document, $this->path('view', $this->recordUuid($person)));
return 'The receipt is ready for signing.'; }),Read the values for the document on the server (from the records), not from the form, and pass only what the view needs.
On the detail page
Section titled “On the detail page”DocumentsComponent lists the documents of a record, newest first:
public function detailComponents(): array{ return ['documents' => new \Anvil\Documents\Ui\DocumentsComponent($this)];}| Column / button | Shown |
|---|---|
| title (download link of signed and final documents), status, created, signer, kept until | always, for users who may view the record |
| Hand over | drafts, for users with the permission of the template |
| Void | drafts, for users with the permission of the template; after a confirmation, with a standard reason |
Without signature
Section titled “Without signature”A template with requiresSignature() returning false is completed
without handover:
$document = service('documents')->create(new DeliveryNote(), $this, $order, $data);service('documents')->finalise($document->uuid); // renders and stores the PDF, status "final"Voiding a draft
Section titled “Voiding a draft”service('documents')->void($document->uuid, 'Wrong items selected.');Only drafts can be voided (DocumentException otherwise); the reason is
stored and audited (document.voided). Signed documents cannot be
changed or voided.
Reading documents
Section titled “Reading documents”Method of service('documents') |
Returns |
|---|---|
find($uuid) |
a Document or null (current tenant) |
forRecord($resource, $record) |
the documents of a record, newest first |
templates(), template($key) |
the registered templates |
html($document) |
the HTML the signer sees |
A Document has uuid, template, title, status, data,
contentHash, fileUuid, pdfHash, signerName, signedAt, createdAt
and retentionUntil.