soli-pdf

Credit note

Names the invoice it corrects, its original amount and the reason. Amounts are negative throughout.

The solid total panel is a rect with spans drawn over it: rect does not advance the cursor, which is what makes an overlay possible.

Overlay panel VAT breakdown Negative amounts 1 page
Page 1
Page 1 of 1
render_credit_note.rb ruby
require 'json'
require 'soli/pdf'

template = JSON.parse(File.read('credit_note.template.json'))
data     = JSON.parse(File.read('credit_note.data.json'))

pdf = Soli::PDF.render(
  template: template,
  data: data,
  title: 'Credit note CN-2025-0031'
)
File.binwrite('credit_note.pdf', pdf)

Run it yourself

  1. Add the gem to your Gemfile — see Installation.
  2. Download credit_note.template.json and credit_note.data.json.
  3. Run ruby render_credit_note.rb.
credit_note.template.json json
{
  "fonts": ["titillium"],
  "options": { "header_height": 0 },
  "footer": [
    { "type": "paragraph", "value": "${seller.name} · ${seller.address} · SIREN ${seller.siren} · VAT ${seller.vat_number} · Page #PAGE# of #TOTAL_PAGE#", "options": { "alignment": "center", "fontSize": 7.5, "color": "6B7280" } }
  ],
  "content": [
    { "type": "hr", "color": "9F1239", "thickness": 3 },
    { "type": "move", "y": 16 },
    {
      "type": "table",
      "header_columns": [
        {
          "content": [
            { "type": "text", "value": "${seller.name}", "fontSize": 15, "fontWeight": "bold" },
            { "type": "text", "value": "${seller.tagline}", "fontSize": 9 }
          ],
          "width": 280, "alignment": "left",
          "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
        },
        {
          "content": [
            { "type": "text", "value": "CREDIT NOTE", "fontSize": 21, "fontWeight": "bold" },
            { "type": "text", "value": "${credit.number}  ·  ${credit.issued}", "fontSize": 9.5 }
          ],
          "width": 201, "alignment": "right",
          "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
        }
      ],
      "rows": [],
      "options": { "header": { "textColor": "9F1239" }, "padding_x": 0, "padding_y": 0 }
    },
    { "type": "move", "y": 20 },

    { "type": "rect", "width": 481, "height": 68, "fill": "FDF2F5", "border": "F0CBD6", "borderWidth": 0.8 },
    { "type": "move", "x": 16, "y": 11 },
    { "type": "paragraph", "spans": [ { "text": "THIS CREDIT NOTE RELATES TO", "fontWeight": "bold", "color": "9F1239" } ], "options": { "fontSize": 7.5 } },
    { "type": "move", "y": 2 },
    { "type": "paragraph", "spans": [
        { "text": "Invoice ${original.number}", "fontWeight": "bold", "color": "1F2937" },
        { "text": "   issued ${original.issued}   ·   original amount ${original.amount}", "color": "5B6B82" }
      ], "options": { "fontSize": 10 } },
    { "type": "move", "y": 3 },
    { "type": "paragraph", "spans": [
        { "text": "Reason  ", "fontWeight": "bold", "color": "9F1239" },
        { "text": "${credit.reason}", "color": "5B6B82" }
      ], "options": { "fontSize": 8.5 } },
    { "type": "move", "x": -16, "y": 30 },

    {
      "type": "table",
      "header_columns": [],
      "rows": [
        [
          {
            "content": [
              { "type": "text", "value": "SUPPLIER", "fontSize": 7.5, "fontWeight": "bold" },
              { "type": "text", "value": "${seller.name}", "fontSize": 10, "fontWeight": "bold" },
              { "type": "text", "value": "${seller.city}", "fontSize": 9 },
              { "type": "text", "value": "SIREN  ${seller.siren}", "fontSize": 9 },
              { "type": "text", "value": "VAT  ${seller.vat_number}", "fontSize": 9 }
            ],
            "width": 240, "alignment": "left", "valign": "top",
            "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
          },
          {
            "content": [
              { "type": "text", "value": "CUSTOMER", "fontSize": 7.5, "fontWeight": "bold" },
              { "type": "text", "value": "${customer.name}", "fontSize": 10, "fontWeight": "bold" },
              { "type": "text", "value": "${customer.city}", "fontSize": 9 },
              { "type": "text", "value": "SIREN  ${customer.siren}", "fontSize": 9 },
              { "type": "text", "value": "VAT  ${customer.vat_number}", "fontSize": 9 }
            ],
            "width": 241, "alignment": "left", "valign": "top",
            "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" }
          }
        ]
      ],
      "options": { "padding_x": 0, "padding_y": 3 }
    },
    { "type": "move", "y": 20 },

    {
      "type": "table",
      "data": "items",
      "header_columns": [
        { "text": "DESCRIPTION", "width": 229, "fontSize": 8, "fontWeight": "bold", "alignment": "left",   "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" } },
        { "text": "QTY",         "width": 40,  "fontSize": 8, "fontWeight": "bold", "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" } },
        { "text": "UNIT PRICE",  "width": 68,  "fontSize": 8, "fontWeight": "bold", "alignment": "right",  "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" } },
        { "text": "VAT",         "width": 40,  "fontSize": 8, "fontWeight": "bold", "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" } },
        { "text": "NET CREDITED","width": 104, "fontSize": 8, "fontWeight": "bold", "alignment": "right",  "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" } }
      ],
      "rows": [
        [
          { "text": "${name}",     "width": 229, "fontSize": 10, "alignment": "left",   "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "${qty}",      "width": 40,  "fontSize": 10, "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "${unit}",     "width": 68,  "fontSize": 10, "alignment": "right",  "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "${vat_rate}", "width": 40,  "fontSize": 10, "alignment": "center", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "${net}",      "width": 104, "fontSize": 10, "alignment": "right",  "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" }
        ]
      ],
      "options": { "header": { "fillColor": "9F1239", "textColor": "FFFFFF", "borderColor": "9F1239" }, "padding_x": 6, "padding_y": 7 }
    },
    { "type": "move", "y": 16 },

    {
      "type": "table",
      "header_columns": [
        { "text": "VAT RATE",     "width": 90,  "fontSize": 8, "fontWeight": "bold", "alignment": "left",  "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "9F1239" },
        { "text": "TAXABLE BASE", "width": 110, "fontSize": 8, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "9F1239" },
        { "text": "VAT CREDITED", "width": 100, "fontSize": 8, "fontWeight": "bold", "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "9F1239" },
        { "text": "",             "width": 181, "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "false" } }
      ],
      "rows": [],
      "options": { "padding_x": 6, "padding_y": 6 }
    },
    {
      "type": "table",
      "data": "vat_breakdown",
      "header_columns": [],
      "rows": [
        [
          { "text": "${rate}",   "width": 90,  "fontSize": 10, "alignment": "left",  "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "${base}",   "width": 110, "fontSize": 10, "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "${amount}", "width": 100, "fontSize": 10, "alignment": "right", "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "true" }, "borderColor": "EFE3E7" },
          { "text": "",          "width": 181, "borderSides": { "top": "false", "left": "false", "right": "false", "bottom": "false" } }
        ]
      ],
      "options": { "padding_x": 6, "padding_y": 6 }
    },
    { "type": "move", "y": 16 },

    {
      "type": "table",
      "header_columns": [],
      "rows": [
        [
          { "text": "", "width": 271, "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } },
          { "text": "Net credited", "width": 130, "fontSize": 10, "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } },
          { "text": "${totals.net}", "width": 80, "fontSize": 10, "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } }
        ],
        [
          { "text": "", "width": 271, "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } },
          { "text": "VAT credited", "width": 130, "fontSize": 10, "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } },
          { "text": "${totals.vat}", "width": 80, "fontSize": 10, "alignment": "right", "borderSides": { "top": "false", "bottom": "false", "left": "false", "right": "false" } }
        ]
      ],
      "options": { "padding_x": 6, "padding_y": 6 }
    },
    { "type": "move", "x": 271, "y": 2 },
    { "type": "rect", "width": 210, "height": 58, "fill": "9F1239" },
    { "type": "move", "x": 16, "y": 12 },
    { "type": "paragraph", "spans": [ { "text": "TOTAL CREDITED", "fontWeight": "bold", "color": "F6D3DC" } ], "options": { "fontSize": 8 } },
    { "type": "move", "y": 3 },
    { "type": "paragraph", "spans": [ { "text": "${totals.credited}", "fontWeight": "bold", "color": "FFFFFF" } ], "options": { "fontSize": 18 } },
    { "type": "move", "x": -287, "y": 26 },

    { "type": "paragraph", "value": "Settlement", "options": { "fontSize": 8, "fontWeight": "bold", "color": "9F1239" } },
    { "type": "move", "y": 3 },
    {
      "type": "list",
      "marker": "—",
      "indent": 10,
      "spacing": 2,
      "items": [
        "${credit.settlement}",
        "This credit note reduces the VAT originally declared on invoice ${original.number}. Adjust your input VAT for the period in which this note is received.",
        "Retain this document with the original invoice for your statutory records."
      ],
      "options": { "fontSize": 8, "color": "4B5A70", "lineHeight": 1.35 }
    }
  ]
}
credit_note.data.json json
{
  "data": {
    "seller": {
      "name": "Meridian Instruments SAS",
      "tagline": "Precision measurement and calibration",
      "address": "18 rue de Paradis",
      "city": "75010 Paris, France",
      "vat_number": "FR75512345679",
      "siren": "512 345 679"
    },
    "customer": {
      "name": "Philharmonie Immobilier SAS",
      "city": "75019 Paris, France",
      "vat_number": "FR22842917361",
      "siren": "842 917 361"
    },
    "credit": {
      "number": "CN-2025-0031",
      "issued": "12 Dec 2025",
      "reason": "Two sensor modules returned unused within the 14-day window, plus a goodwill credit for the rescheduled calibration visit.",
      "settlement": "The credited amount is refunded to the original bank account within 14 days, or offset against the next invoice if you prefer — reply to this note to choose."
    },
    "original": {
      "number": "MI-2025-0184",
      "issued": "28 Nov 2025",
      "amount": "€2,430.21"
    },
    "items": [
      { "name": "Sensor module MX-4, returned unused", "qty": "-2", "unit": "145.00", "vat_rate": "20%", "net": "-290.00" },
      { "name": "Goodwill credit, rescheduled site visit", "qty": "-1", "unit": "120.00", "vat_rate": "20%", "net": "-120.00" }
    ],
    "vat_breakdown": [
      { "rate": "20%", "base": "-410.00", "amount": "-82.00" }
    ],
    "totals": {
      "net": "-€410.00",
      "vat": "-€82.00",
      "credited": "-€492.00"
    }
  }
}