Rendro.Recipes.Invoice (Rendro v0.3.0)

Copy Markdown View Source

Canonical invoice recipe using the Tiered Composition pattern.

Exposes three levels of composability:

  • document/2 — Batteries-included; returns a fully assembled
                    `%Rendro.Document{}` ready for `Rendro.render/1`.
  • page_template/1 — Layout only; returns the %Rendro.PageTemplate{}.
  • sections/2 — Content only; returns a list of %Rendro.Section{}
                    structs mapped to named regions.

Usage

Zero-to-one (just works)

data = %{id: "INV-001", date: ~D[2026-01-15], items: [...]}
doc  = Rendro.Recipes.Invoice.document(data)
{:ok, pdf} = Rendro.render(doc)

Escape hatch — inject a custom template

template = Rendro.Recipes.Invoice.page_template(name: :branded)
sections = Rendro.Recipes.Invoice.sections(data)
doc =
  Rendro.Document.new()
  |> Rendro.Document.add_template(template)
  |> Rendro.Document.set_template(:branded)
  |> then(fn d -> Enum.reduce(sections, d, &Rendro.Document.add_section(&2, &1)) end)

Summary

Functions

Assembles and returns a fully composed %Rendro.Document{} using the pipeline builder API.

Returns a %Rendro.PageTemplate{} with three named regions: :header, :body, :footer.

Returns a list of %Rendro.Section{} structs mapping invoice content to the :header, :body, and :footer regions.

Functions

document(data, opts \\ [])

@spec document(
  map(),
  keyword()
) :: Rendro.Document.t()

Assembles and returns a fully composed %Rendro.Document{} using the pipeline builder API.

Uses page_template/1 and sections/2 internally, then chains them through Rendro.Document.new/0 |> add_template |> set_template |> add_section.

Examples

iex> data = %{id: "INV-001", date: ~D[2026-01-15], items: []}
iex> doc = Rendro.Recipes.Invoice.document(data)
iex> doc.page_template
:invoice

page_template(opts \\ [])

@spec page_template(keyword()) :: Rendro.PageTemplate.t()

Returns a %Rendro.PageTemplate{} with three named regions: :header, :body, :footer.

Options

All options are forwarded to %Rendro.PageTemplate{} as keyword overrides. The name defaults to :invoice.

Examples

iex> Rendro.Recipes.Invoice.page_template()
%Rendro.PageTemplate{name: :invoice, ...}

iex> Rendro.Recipes.Invoice.page_template(name: :branded)
%Rendro.PageTemplate{name: :branded, ...}

sections(data, opts \\ [])

@spec sections(
  map(),
  keyword()
) :: [Rendro.Section.t()]

Returns a list of %Rendro.Section{} structs mapping invoice content to the :header, :body, and :footer regions.

Examples

iex> data = %{id: "INV-001", date: ~D[2026-01-15], items: []}
iex> [header, body, footer] = Rendro.Recipes.Invoice.sections(data)
iex> header.region
:header