receipts Ruby gem

repository·main·Indexed 20 days ago

https://github.com/excid3/receipts

A Ruby gem for generating professional PDF Receipts, Invoices, and Statements for Rails applications. Built on the Prawn library, it provides classes like Receipts::Receipt, Receipts::Invoice, and Receipts::Statement to render documents with customizable company details, recipient information, line items with HTML-like formatting, and custom fonts.

Tokens
2.7K
Snippets
10
Records
15
Agent score
70%

What's inside receipts

  1. Use inline formatting in details and line items

    main

    The details and line_items arrays support inline formatting using Prawn-compatible HTML-like tags:

    • <b> (bold)
    • <i> (italic)
    • <u> (underline)
    • <strikethrough>
    • <sub> (subscript)
    • <sup> (superscript)
    • <font>
    • <color>
    • <link>
  2. Generate a Receipt, Invoice, or Statement

    main

    To generate a document, instantiate Receipts::Receipt, Receipts::Invoice, or Receipts::Statement with a configuration hash. You can then use .render to get the raw PDF string or .render_file to save it to disk.

    r = Receipts::Receipt.new(
      details: [
        ["Receipt Number", "123"],
        ["Date paid", Date.today]
      ],
      company: {
        name: "Example, LLC",
        address: "123 Fake Street\nNew York City, NY 10012",
        email: "support@example.com",
        logo: File.expand_path("./logo.png")
      },
      recipient: [
        "Customer",
        "Their Address",
        "City, State Zipcode",
        nil,
        "customer@example.org"
      ],
      line_items: [
        ["<b>Item</b>", "<b>Unit Cost</b>", "<b>Quantity</b>", "<b>Amount</b>"],
        ["Subscription", "$19.00", "1", "$19.00"]
      ],
      footer: "Thanks for your business."
    )
    
    # Returns a string of the raw PDF
    r.render
    
    # Writes the PDF to disk
    r.render_file "examples/receipt.pdf"
  3. Serve PDFs in a Rails controller

    main

    To serve a PDF in a Rails controller, use the .render method to get the raw PDF string and pass it to send_data. Set the type to application/pdf and choose a disposition (:inline to view in browser, :attachment to download).

    class ChargesController < ApplicationController
      # ... setup code ...
    
      def show
        respond_to do |format| 
          format.pdf { send_pdf }
        end
      end
    
      private
    
      def send_pdf
        # @charge.receipt returns a Receipts::Receipt instance
        send_data @charge.receipt.render,
          filename: "#{@charge.created_at.strftime('%Y-%m-%d')}-receipt.pdf",
          type: "application/pdf",
          disposition: :inline
      end
    end
  4. Access the main Receipts module entrypoints

    main

    The Receipts module serves as the primary entrypoint for the gem. It provides access to the following core document types via autoloading:

    • Receipts::Receipt: For generating individual receipts.
    • Receipts::Invoice: For generating invoices.
    • Receipts::Statement: For generating account statements.
    • Receipts::Base: The base class for document generation logic.
  5. Configure default fonts for all PDFs

    main

    Set a global default font for all generated PDFs by defining Receipts.default_font in an initializer. The hash requires :bold and :normal keys pointing to valid font file paths.

    Receipts.default_font = {
      bold: Rails.root.join('app/assets/fonts/tradegothic/TradeGothic-Bold.ttf'),
      normal: Rails.root.join('app/assets/fonts/tradegothic/TradeGothic.ttf'),
    }
  6. Customize company details and logo

    main

    The header and render_billing_details methods use the company hash to populate the document.

    Logo Handling If company[:logo] is provided, it is rendered at the top right. The load_image method supports:

    • A URL (string starting with http).
    • A local file path.
    • An existing image object.

    Billing Details render_billing_details displays company information and recipient information in a table. By default, it displays the company's :address, :phone, and :email. You can control which fields are shown by providing a :display array in the company hash.

    Example Company Hash:

    company = {
      name: "Acme Corp",
      logo: "https://example.com/logo.png",
      email: "contact@acme.com",
      address: "123 Main St",
      phone: "555-0123",
      display: [:address, :email] # Only show address and email
    }
  7. Create custom PDF content with Receipts helpers

    main

    You can bypass the standard template by instantiating a Receipt object without options: Receipts::Receipt.new. Since every Receipts object inherits from Prawn::Document, you can use standard Prawn methods like .text or use Receipts-specific helpers at the current cursor position:

    • render_line_items(line_items: [...])
    • render_footer(text)
    receipt = Receipts::Receipt.new # creates an empty PDF
    
    receipt.text("hello world")
    
    # Using helpers
    receipt.text("Custom header")
    receipt.render_line_items(line_items: [["my line items"]])
    receipt.render_footer("This is a custom footer using the Receipts helper")
  8. Configure default fonts for Receipts

    main

    You can set a global default font configuration for all receipt, invoice, and statement generation. The configuration expects a hash containing paths to your font files for bold and normal styles. This is useful when using custom TTF or OTF fonts via the underlying Prawn engine.

    Receipts.default_font = {
      bold: "path/to/bold-font.ttf",
      normal: "path/to/normal-font.ttf"
    }
  9. Configure line item column widths

    main

    To fix layout issues where Prawn's width guessing fails, you can explicitly set column widths for the line_items table using the column_widths option. This follows Prawn's table configuration.

    • Use a Hash for specific columns: {1 => 400, 3 => 50} (sets column 1 to 400 and column 3 to 50).
    • Use an Array for all columns: [100, 200, 240].
    # Example using a Hash for specific columns
    column_widths: {1 => 400, 3 => 50}
    
    # Example using an Array for all columns
    column_widths: [100, 200, 240]
  10. Configure Receipt options

    main

    When instantiating a Receipt, Invoice, or Statement, you can pass several options to customize the output:

    • recipient (Array): Customer details (name, address, email, etc.).
    • company (Hash): Company details.
      • name (String): Company name.
      • address (String): Company address.
      • email (String): Support email.
      • phone (String, optional): Phone number.
      • logo (Path, File, StringIO, or URL, optional): Logo image.
      • display (Array of Symbols, optional): Which company keys to render (default: [:address, :phone, :email]).
    • details (Array): Key-value pairs for metadata (e.g., receipt number, date).
    • line_items (Array): Table data for items. Supports HTML-like formatting.
    • footer (String): Message at the bottom.
    • font (Hash, optional): Specific font paths for this instance (bold and normal).
    • logo_height (Integer, optional): Height of the logo. Defaults to 16.
    • page_size (String, optional): e.g., "A4".
  11. Initialize and generate a receipt using Receipts::Base

    main

    To generate a receipt, create a subclass of Receipts::Base and instantiate it with an attributes hash. The initialize method accepts configuration for page_size and font. The generate_from method orchestrates the document layout by processing the following required keys in the attributes hash:

    • company: A hash containing company information (e.g., :name, :logo, :email, :address, :phone, :display).
    • details: Data to be rendered in the details section via render_details.
    • recipient: The recipient of the receipt.
    • line_items: An array of line items to be rendered in a table.
    • footer (optional): A custom message for the footer. If omitted, a default message using the company's email is generated.

    Optional keys include:

    • logo_height: Height for the company logo (defaults to 16).
    • column_widths: Custom widths for the line items table.

    Note: Receipts::Base inherits from Prawn::Document, so standard Prawn functionality is available.

    class MyReceipt < Receipts::Base
      self.title = "Sales Receipt"
    end
    
    MyReceipt.new(
      page_size: "A4",
      title: "Custom Title",
      company: { name: "Acme Corp", email: "help@acme.com" },
      details: [["Date", "2023-01-01"]],
      recipient: "John Doe",
      line_items: [["Item", "Price"]],
      footer: "Thank you!"
    )