NetSuite Invoice PDFs: How to Display Days Open Automatically
A NetSuite days open custom field on an invoice PDF gives finance teams and customers immediate visibility into how long an invoice has remained outstanding. The challenge is that “days open” is a changing value, while a NetSuite transaction body field stores a value until something updates it.
The most reliable approach is to define the calculation first, then choose how NetSuite should refresh it. For a simple printed invoice, an Advanced PDF/HTML Template can display a custom transaction field. For a value that must remain current every day, we recommend calculating days open at print time with SuiteScript or updating the field through a scheduled process. The template then references that value with a FreeMarker expression such as `${record.custbody_days_open}`.
This article focuses specifically on displaying a changing invoice-age value on printed or emailed invoices. For the broader setup process involving date-driven workflow automation, see our guide on using NetSuite workflows to auto-populate fields based on transaction dates.
What does “days open” mean on a NetSuite invoice?
“Days open” is the number of calendar days between the invoice date and the date used for the calculation, generally today or the invoice settlement date. An invoice issued on April 1 and printed on April 11 has 10 days open when using a simple calendar-day calculation.
The calculation needs a clear business definition:
Open invoice: Today minus the invoice date.
Paid invoice: Payment or settlement date minus the invoice date.
Partially paid invoice: Today minus the invoice date, unless your policy measures the age of the remaining balance separately.
Voided invoice: Exclude the invoice or display a status such as “Voided.”
Future-dated invoice: Return zero or flag the record for review rather than showing a negative number.
NetSuite has several dates that look similar but produce different results. The Transaction Date represents the invoice date. The Due Date measures payment terms. The Date Closed value is relevant when the invoice is fully paid or otherwise closed. A “days past due” field should use the due date, while a “days open” field generally uses the transaction date.
That distinction matters on the PDF. If the label says Days Open, calculating from the due date creates a misleading result because it measures lateness rather than invoice age.
Which NetSuite field should appear on the invoice PDF?
The best field type is a transaction body custom field created for the invoice record type. A body field is appropriate because the value describes the invoice as a whole, not an individual item line.
A typical configuration includes:
| Setting | Recommended choice |
|---|---|
| Record type | Transaction |
| Applies to | Invoice |
| Type | Integer Number |
| Store Value | Depends on the calculation method |
| Display | Forms and printed output as needed |
| Label | Days Open |
| ID example | `custbody_days_open` |
The internal ID is what the Advanced PDF/HTML Template uses. The visible label can be “Days Open,” “Invoice Age,” or another term that matches your collections policy.
Stored versus calculated custom fields
A stored field saves a value on the transaction. That makes it easy to search, report, export, and merge into a PDF. However, the value becomes stale unless a workflow, script, or scheduled process updates it.
A non-stored or formula-based field calculates from other values. This avoids some manual updates, but formula behavior depends on where the field is used and which date functions NetSuite supports in that context. A formula that works in a saved search is not automatically interchangeable with a transaction field or Advanced PDF template expression.
For printed invoices, we recommend treating the field and the PDF as separate layers:
Calculation layer: Determines the correct number.
Transaction layer: Stores or exposes the number.
Presentation layer: Prints the number in the invoice template.
Keeping those layers separate makes troubleshooting much easier.
How do you add a days open field in NetSuite?
Create the custom field before editing the PDF template. This gives NetSuite a defined internal ID that the template can reference.
Navigate to Customization > Lists, Records, & Fields > Transaction Body Fields > New, then configure the field for invoices. The exact menu labels can vary by account features and role permissions, but the important choices remain the same.
Use an integer number field rather than a free-form text field. An integer supports sorting, filtering, saved searches, and validation. Set the field to display on the invoice form if users need to review it, but consider hiding it from data-entry forms if users should never type into it manually.
The Store Value setting requires a deliberate decision:
Select stored behavior when a script or scheduled process will write the value.
Avoid allowing ordinary users to edit the field if the number is system-generated.
Use field-level permissions or form customization to protect the value.
Make the field available to the relevant invoice forms and roles.
Confirm that the field is available in the transaction record used by the PDF template.
After creating the field, open an invoice and confirm that the field appears. Record the field’s internal ID from the custom field page. The display label is not sufficient for FreeMarker references.
How do you calculate days open accurately?
The calculation should use date-only values and a documented treatment of closed transactions. Date-time conversions create unexpected results when the account, user, script, and customer operate in different time zones.
For an open invoice, the basic calculation is:
Days Open = Current Date − Invoice Transaction Date
For a closed invoice, the calculation may be:
Days Open = Date Closed − Invoice Transaction Date
A SuiteScript implementation should normalize both dates before subtracting them. In JavaScript, date objects include time components, so subtracting two raw values can produce a result that is off by one day. The script should either use NetSuite’s formatted date values consistently or normalize both dates to midnight in the account’s intended time zone.
A calculation also needs a status rule. For example, a paid invoice should not continue increasing forever if the business wants to show the age at settlement. Conversely, accounts receivable teams may intentionally want the PDF to show the invoice’s current age even after a partial payment.
Document these rules in the field description or technical design:
Which date starts the count?
Does the count include the invoice date?
Does the count stop when the invoice closes?
How should credits, deposits, and write-offs affect the value?
Should the PDF show a number for paid invoices?
What should happen when the invoice date is in the future?
Without these decisions, two teams can implement different “correct” calculations.
How can you keep the field current?
A stored custom field does not refresh simply because a day passes. NetSuite does not continuously recalculate ordinary stored transaction fields in the background. The refresh mechanism must match the required accuracy.
SuiteScript at print or view time
A User Event script can calculate the value during record access or before rendering, depending on the required output and account design. This approach avoids writing a new value to every invoice each day, but it requires testing to confirm that the value is available to the print process and does not unintentionally persist changes.
A dedicated rendering script provides stronger control. The script loads the invoice, calculates days open, and passes the result into the PDF rendering process. This is particularly useful when the PDF is generated from a Suitelet or another controlled script rather than only from NetSuite’s native Print button.
SuiteScript 2.1 is the current scripting framework to use for new development. The script should include governance-conscious record loading, clear handling for missing dates, and tests for open, paid, partially paid, voided, and future-dated invoices.
Scheduled or Map/Reduce updates
A scheduled script or Map/Reduce script can update open invoices once per day. This is the most straightforward option when the custom field must be available in saved searches, dashboards, workflows, and standard invoice PDFs.
Map/Reduce is a better fit than a basic scheduled script when the account has a large number of open invoices or needs restartability and controlled governance usage. The process should search only records that require updates, such as open invoices or invoices whose calculated value has changed.
A daily update produces a value that is accurate as of the last scheduled run, not necessarily at the moment someone prints the invoice. That distinction should be visible in internal documentation.
Workflow updates
A workflow can populate a field when a transaction is created, edited, approved, or moved through a defined status. It is useful for event-based updates, such as setting an initial value when an invoice is created.
A workflow alone is not a complete solution for a value that changes every day. A time-based workflow or scheduled action might support periodic updates, but the account must be tested carefully because workflow timing, execution context, and record state affect when the value changes.
How do you add the field to an Advanced PDF template?
Once the field produces the expected value, update the invoice’s Advanced PDF/HTML Template.
Go to Customization > Forms > Advanced PDF/HTML Templates, open the invoice template, and locate the section where the value should appear. The exact FreeMarker expression depends on the field ID. If the ID is `custbody_days_open`, the reference will typically resemble:
<span>Days Open: ${record.custbody_days_open}</span>Use the field’s internal ID, not its label. If the field is empty, protect the output with a conditional:
<#if record.custbody_days_open?has_content>
<span>Days Open: ${record.custbody_days_open}</span>
</#if>If the value should display as zero when blank, use a default expression only after confirming that a blank field truly means zero in the business process. A blank value might instead indicate that the script failed, the invoice is excluded, or the field is unavailable in the rendering context.
For a clean presentation, place the value near the invoice date and due date, or in a clearly labeled aging section. Do not place “Days Open” beside “Days Past Due” without distinct labels. The two metrics answer different questions.
Why is the custom field blank on the invoice PDF?
A blank PDF field generally indicates a configuration or rendering problem, not an issue with the HTML layout alone. Check the field internal ID first, then confirm that the value exists on the invoice being printed.
The most common causes are:
The template references the display label instead of the internal ID.
The field does not apply to the invoice record type.
The field is hidden from the form or role context.
The script populates a different custom field.
The field is populated only during a user event that does not run in the relevant print context.
The invoice uses a different custom form or template.
The value is blank because the source date or status is missing.
The PDF is generated by a Suitelet or integration that uses a different data source.
The field is not available under the `record` object exposed to that template.
Use a controlled test invoice and inspect the field directly in NetSuite. Then print the same record from the same role and form used by the finance team. Testing only as an administrator can hide permission problems.
If the value appears on-screen but not in the PDF, isolate the presentation layer. If it is absent both on-screen and in the PDF, investigate the calculation or update mechanism first.
What is the best implementation method?
The best method depends on where the value is needed and how current it must be.
| Requirement | Best-fit approach |
|---|---|
| Show the value on a PDF generated on demand | Calculate during rendering with SuiteScript |
| Search and report on days open | Store the value and update it on a schedule |
| Set an initial value at invoice creation | Workflow or User Event script |
| Support large invoice volumes | Map/Reduce update process |
| Avoid custom code for a static value | Template display of an existing, stable field |
| Display both current age and historical age | Use separate calculated definitions and fields |
For most accounts, we recommend a stored integer field plus a controlled scheduled update when reporting and standard printing are important. If real-time accuracy is more important than searchability, calculate the value at rendering time instead.
Do not create several fields with nearly identical names, such as `Days Open`, `Invoice Age`, and `Current Days Open`, unless they represent intentionally different calculations. Duplicate fields create confusion in workflows, searches, templates, and integrations.
Testing checklist for NetSuite invoice PDFs
Test the feature with records that exercise the calculation rules, not just one current invoice. A practical test set includes an open invoice created today, an older open invoice, a paid invoice, a partially paid invoice, a voided invoice, and an invoice with a future transaction date.
Also test the output under the conditions that matter operationally:
Native NetSuite printing
Emailing the invoice as a PDF
Downloading the PDF
Different invoice forms
Different roles and permissions
Multiple subsidiaries, if applicable
Account and user time-zone differences
Blank or missing source dates
Long and short customer names
Multiple currencies and tax configurations
Review the PDF visually as well as technically. A correct field value is not enough if the label wraps, overlaps another element, or appears in a section customers do not understand.
If the invoice is customer-facing, decide whether displaying days open supports the intended communication. Some organizations prefer the value on internal statements and collections documents rather than on every invoice. The template should reinforce the process, not introduce a new source of confusion.
When should you use SuiteScript instead of only a PDF template?
Use SuiteScript when the value must be calculated dynamically, when the native template lacks the required source data, or when the PDF must combine multiple transaction rules. A template is a presentation layer, not a general-purpose calculation engine.
SuiteScript also makes sense when the invoice PDF is generated through a custom Suitelet, email automation, or integration. In those cases, a script can supply a calculated value through a custom data source or rendering context instead of relying on a stored transaction field.
For more complex customization, our NetSuite development and customization team can help define the field logic, script context, template reference, and testing plan. The goal is to make the displayed number consistent across printed documents, searches, workflows, and reporting.
Conclusion
Displaying a days open value on a NetSuite invoice PDF requires more than adding a text field to the template. The calculation must distinguish invoice age from payment lateness, handle open and closed transactions correctly, and refresh at the level of accuracy the business requires.
A custom transaction body field works well when paired with a scheduled update process. For on-demand, current PDFs, SuiteScript-based rendering provides better control. Once the calculation is reliable, the Advanced PDF/HTML Template can display the internal field value clearly and consistently.
The result is a customer document that communicates invoice age without manual data entry, while keeping the underlying logic available for searches, workflows, and finance reporting.
