invoice_printer 2.2.0.alpha1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Dockerfile +2 -2
- data/Gemfile.lock +7 -7
- data/README.md +1 -1
- data/assets/fonts/opensans/OpenSans-Bold.ttf +0 -0
- data/assets/fonts/overpass/Overpass-Bold.ttf +0 -0
- data/assets/fonts/roboto/Roboto-Bold.ttf +0 -0
- data/bin/invoice_printer +7 -0
- data/docs/COMMAND_LINE.md +2 -1
- data/docs/LIBRARY.md +1 -0
- data/docs/SERVER.md +2 -0
- data/examples/breakdown.rb +77 -0
- data/examples/long_invoice.rb +4 -4
- data/examples/promo.rb +2 -0
- data/invoice_printer_fonts.gemspec +3 -0
- data/lib/invoice_printer.rb +26 -2
- data/lib/invoice_printer/document/item.rb +34 -28
- data/lib/invoice_printer/pdf_document.rb +75 -52
- data/lib/invoice_printer/version.rb +1 -1
- data/test/examples_test.rb +2 -0
- data/test/test_ext.rb +2 -1
- metadata +9 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 33a87300d4ff6a12080b758ea012b7c94a09521575c99579e300844dbfbf0e47
         | 
| 4 | 
            +
              data.tar.gz: 33446dc1314512a7793ad95b73065dfb59abef1963e5c115fab5263e2dd53ecc
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ef29b3e26227c6cbeba87fca78154d55a7bb103472f77991fe1a4df24f30a36efa75db3f7f724ddd17a369713870db6d20bd93ea33d0812fb55501bbba9c7ea2
         | 
| 7 | 
            +
              data.tar.gz: 6c93d97f040190c555dcbdaf742e05d904a00bd458e2f68009dd1191ec3bf190fe92e20033bb19e0ae3337f6e10686361922b05bcfcc6316e86f8bb46b7a0cbf
         | 
    
        data/Dockerfile
    CHANGED
    
    | @@ -26,10 +26,10 @@ RUN apk update && apk upgrade | |
| 26 26 | 
             
            RUN apk add build-base bash ruby ruby-etc ruby-dev
         | 
| 27 27 |  | 
| 28 28 | 
             
            # Install builtin fonts
         | 
| 29 | 
            -
            RUN gem install invoice_printer_fonts --version 2. | 
| 29 | 
            +
            RUN gem install invoice_printer_fonts --version 2.2.0 --no-document
         | 
| 30 30 |  | 
| 31 31 | 
             
            # Install the gem from RubyGems.org
         | 
| 32 | 
            -
            RUN gem install invoice_printer_server --version 2. | 
| 32 | 
            +
            RUN gem install invoice_printer_server --version 2.2.0 --no-document
         | 
| 33 33 |  | 
| 34 34 | 
             
            # Clean APK cache
         | 
| 35 35 | 
             
            RUN rm -rf /var/cache/apk/*
         | 
    
        data/Gemfile.lock
    CHANGED
    
    | @@ -1,12 +1,12 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 2 | 
             
              remote: .
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                invoice_printer (2. | 
| 4 | 
            +
                invoice_printer (2.2.0)
         | 
| 5 5 | 
             
                  json (~> 2.1)
         | 
| 6 6 | 
             
                  prawn (~> 2.2)
         | 
| 7 7 | 
             
                  prawn-table (~> 0.2.2)
         | 
| 8 | 
            -
                invoice_printer_server (2. | 
| 9 | 
            -
                  invoice_printer (= 2. | 
| 8 | 
            +
                invoice_printer_server (2.2.0)
         | 
| 9 | 
            +
                  invoice_printer (= 2.2.0)
         | 
| 10 10 | 
             
                  json (~> 2.1)
         | 
| 11 11 | 
             
                  puma (>= 3.9.0)
         | 
| 12 12 | 
             
                  roda (~> 3.5)
         | 
| @@ -25,9 +25,9 @@ GEM | |
| 25 25 | 
             
                  rmagick
         | 
| 26 26 | 
             
                hashery (2.1.2)
         | 
| 27 27 | 
             
                histogram (0.2.4.1)
         | 
| 28 | 
            -
                json (2. | 
| 28 | 
            +
                json (2.5.1)
         | 
| 29 29 | 
             
                minitest (5.14.2)
         | 
| 30 | 
            -
                nio4r (2.5. | 
| 30 | 
            +
                nio4r (2.5.7)
         | 
| 31 31 | 
             
                pdf-core (0.9.0)
         | 
| 32 32 | 
             
                pdf-inspector (1.3.0)
         | 
| 33 33 | 
             
                  pdf-reader (>= 1.0, < 3.0.a)
         | 
| @@ -42,14 +42,14 @@ GEM | |
| 42 42 | 
             
                  ttfunk (~> 1.7)
         | 
| 43 43 | 
             
                prawn-table (0.2.2)
         | 
| 44 44 | 
             
                  prawn (>= 1.3.0, < 3.0.0)
         | 
| 45 | 
            -
                puma (5. | 
| 45 | 
            +
                puma (5.3.2)
         | 
| 46 46 | 
             
                  nio4r (~> 2.0)
         | 
| 47 47 | 
             
                rack (2.2.3)
         | 
| 48 48 | 
             
                rack-test (1.1.0)
         | 
| 49 49 | 
             
                  rack (>= 1.0, < 3)
         | 
| 50 50 | 
             
                rake (13.0.1)
         | 
| 51 51 | 
             
                rmagick (4.1.2)
         | 
| 52 | 
            -
                roda (3. | 
| 52 | 
            +
                roda (3.45.0)
         | 
| 53 53 | 
             
                  rack
         | 
| 54 54 | 
             
                ruby-rc4 (0.1.5)
         | 
| 55 55 | 
             
                ttfunk (1.7.0)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -25,7 +25,7 @@ See more usecases in the `examples/` directory. | |
| 25 25 | 
             
            - Purchaser and provider boxes with addresses and identificaton numbers
         | 
| 26 26 | 
             
            - Payment method box showing banking details including SWIFT and IBAN fields
         | 
| 27 27 | 
             
            - Issue/due dates box
         | 
| 28 | 
            -
            - Configurable items' table with item description, quantity, unit, price per unit, tax and item's total amount fields
         | 
| 28 | 
            +
            - Configurable items' table with item description, breakdown, quantity, unit, price per unit, tax and item's total amount fields
         | 
| 29 29 | 
             
            - Final subtotal/tax/total info box
         | 
| 30 30 | 
             
            - Page numbers
         | 
| 31 31 | 
             
            - Configurable field labels & sublabels (optional little labels)
         | 
| Binary file | 
| Binary file | 
| Binary file | 
    
        data/bin/invoice_printer
    CHANGED
    
    | @@ -19,6 +19,7 @@ def show_help | |
| 19 19 | 
             
                  -d, --document   document as JSON
         | 
| 20 20 | 
             
                    -l, --labels   labels as JSON
         | 
| 21 21 | 
             
                          --font   path to font or builtin font name
         | 
| 22 | 
            +
                     --bold-font   path to bold font or builtin font name
         | 
| 22 23 | 
             
                     -s, --stamp   path to stamp
         | 
| 23 24 | 
             
                          --logo   path to logotype
         | 
| 24 25 | 
             
                    --background   path to background image
         | 
| @@ -47,6 +48,10 @@ parser = OptionParser.new do|opts| | |
| 47 48 | 
             
                options[:font] = path
         | 
| 48 49 | 
             
              end
         | 
| 49 50 |  | 
| 51 | 
            +
              opts.on('--bold-font PATH') do |path|
         | 
| 52 | 
            +
                options[:bold_font] = path
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 50 55 | 
             
              opts.on('-s', '--stamp PATH') do |path|
         | 
| 51 56 | 
             
                options[:stamp] = path
         | 
| 52 57 | 
             
              end
         | 
| @@ -116,6 +121,7 @@ begin | |
| 116 121 | 
             
                  document:   document,
         | 
| 117 122 | 
             
                  labels:     labels,
         | 
| 118 123 | 
             
                  font:       options[:font],
         | 
| 124 | 
            +
                  bold_font:  options[:bold_font],
         | 
| 119 125 | 
             
                  stamp:      options[:stamp],
         | 
| 120 126 | 
             
                  logo:       options[:logo],
         | 
| 121 127 | 
             
                  background: options[:background],
         | 
| @@ -130,6 +136,7 @@ begin | |
| 130 136 | 
             
                  document:   document,
         | 
| 131 137 | 
             
                  labels:     labels,
         | 
| 132 138 | 
             
                  font:       options[:font],
         | 
| 139 | 
            +
                  bold_font:  options[:bold_font],
         | 
| 133 140 | 
             
                  stamp:      options[:stamp],
         | 
| 134 141 | 
             
                  logo:       options[:logo],
         | 
| 135 142 | 
             
                  file_name:  options[:filename],
         | 
    
        data/docs/COMMAND_LINE.md
    CHANGED
    
    | @@ -13,6 +13,7 @@ Options: | |
| 13 13 | 
             
              -d, --document   document as JSON
         | 
| 14 14 | 
             
                -l, --labels   labels as JSON
         | 
| 15 15 | 
             
                      --font   path to font or builtin font name
         | 
| 16 | 
            +
                 --bold-font   path to bold font or builtin font name
         | 
| 16 17 | 
             
                 -s, --stamp   path to stamp
         | 
| 17 18 | 
             
                      --logo   path to logotype
         | 
| 18 19 | 
             
                --background   path to background image
         | 
| @@ -139,7 +140,7 @@ All labels: | |
| 139 140 |  | 
| 140 141 | 
             
            ## Built-in fonts
         | 
| 141 142 |  | 
| 142 | 
            -
            Supported builtin fonts are: `overpass`, `opensans`, and `roboto`.
         | 
| 143 | 
            +
            Supported builtin fonts are: `overpass`, `opensans`, and `roboto`. They ship with bold versions.
         | 
| 143 144 |  | 
| 144 145 | 
             
            ## Examples
         | 
| 145 146 |  | 
    
        data/docs/LIBRARY.md
    CHANGED
    
    
    
        data/docs/SERVER.md
    CHANGED
    
    | @@ -61,6 +61,7 @@ Options: | |
| 61 61 | 
             
            - `document` - JSON representation of the document
         | 
| 62 62 | 
             
            - `labels` - JSON for labels
         | 
| 63 63 | 
             
            - `font` - path to font file or builtin font name
         | 
| 64 | 
            +
            - `bold_font` - path to bold font file or builtin font name
         | 
| 64 65 | 
             
            - `stamp` - path to stamp file
         | 
| 65 66 | 
             
            - `logo` - path to logotype file
         | 
| 66 67 | 
             
            - `background` - path to background file
         | 
| @@ -103,6 +104,7 @@ Options: | |
| 103 104 | 
             
            - `document` - JSON representation of the document
         | 
| 104 105 | 
             
            - `labels` - JSON for labels
         | 
| 105 106 | 
             
            - `font` - path to font file or builtin font name
         | 
| 107 | 
            +
            - `bold_font` - path to bold font file or builtin font name
         | 
| 106 108 | 
             
            - `stamp` - path to stamp file
         | 
| 107 109 | 
             
            - `logo` - path to logotype file
         | 
| 108 110 | 
             
            - `background` - path to background file
         | 
| @@ -0,0 +1,77 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
            # This is an example of a longer invoice.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            lib = File.expand_path('../../lib', __FILE__)
         | 
| 5 | 
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| 6 | 
            +
            require 'invoice_printer'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            labels = {
         | 
| 9 | 
            +
              tax: '10% VAT'
         | 
| 10 | 
            +
            }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            item = InvoicePrinter::Document::Item.new(
         | 
| 13 | 
            +
              name: 'Programming',
         | 
| 14 | 
            +
              quantity: '10',
         | 
| 15 | 
            +
              unit: 'h',
         | 
| 16 | 
            +
              price: '$ 60',
         | 
| 17 | 
            +
              tax: '$ 60',
         | 
| 18 | 
            +
              amount: '$ 600'
         | 
| 19 | 
            +
            )
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            item2 = InvoicePrinter::Document::Item.new(
         | 
| 22 | 
            +
              name: 'Consulting',
         | 
| 23 | 
            +
              breakdown: "Excludes 1 hour free consultation",
         | 
| 24 | 
            +
              quantity: '10',
         | 
| 25 | 
            +
              unit: 'h',
         | 
| 26 | 
            +
              price: '$ 30',
         | 
| 27 | 
            +
              tax: '$ 30',
         | 
| 28 | 
            +
              amount: '$ 300'
         | 
| 29 | 
            +
            )
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            breakdown = <<BREAKDOWN
         | 
| 32 | 
            +
            Issue 404: 15h
         | 
| 33 | 
            +
            Issue 505: 5h
         | 
| 34 | 
            +
            BREAKDOWN
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            item3 = InvoicePrinter::Document::Item.new(
         | 
| 37 | 
            +
              name: 'Support',
         | 
| 38 | 
            +
              breakdown: breakdown,
         | 
| 39 | 
            +
              quantity: '20',
         | 
| 40 | 
            +
              unit: 'h',
         | 
| 41 | 
            +
              price: '$ 15',
         | 
| 42 | 
            +
              tax: '$ 30',
         | 
| 43 | 
            +
              amount: '$ 330'
         | 
| 44 | 
            +
            )
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            invoice = InvoicePrinter::Document.new(
         | 
| 47 | 
            +
              number: 'NO. 198900000001',
         | 
| 48 | 
            +
              provider_name: 'John White',
         | 
| 49 | 
            +
              provider_lines: "79 Stonybrook St.\nBronx, NY 10457",
         | 
| 50 | 
            +
              purchaser_name: 'Will Black',
         | 
| 51 | 
            +
              purchaser_lines: "8648 Acacia Rd.\nBrooklyn, NY 11203",
         | 
| 52 | 
            +
              issue_date: '05/03/2016',
         | 
| 53 | 
            +
              due_date: '19/03/2016',
         | 
| 54 | 
            +
              subtotal: '$ 1,000',
         | 
| 55 | 
            +
              tax: '$ 100',
         | 
| 56 | 
            +
              total: '$ 1,100',
         | 
| 57 | 
            +
              bank_account_number: '156546546465',
         | 
| 58 | 
            +
              items: [item, item2, item3],
         | 
| 59 | 
            +
              note: 'This is a note at the end.'
         | 
| 60 | 
            +
            )
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            InvoicePrinter.print(
         | 
| 63 | 
            +
              document: invoice,
         | 
| 64 | 
            +
              labels: labels,
         | 
| 65 | 
            +
              stamp: File.expand_path('../stamp.png', __FILE__),
         | 
| 66 | 
            +
              logo: File.expand_path('../prawn.png', __FILE__),
         | 
| 67 | 
            +
              file_name: 'breakdown.pdf'
         | 
| 68 | 
            +
            )
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            InvoicePrinter.print(
         | 
| 71 | 
            +
              document: invoice,
         | 
| 72 | 
            +
              labels: labels,
         | 
| 73 | 
            +
              stamp: File.expand_path('../stamp.png', __FILE__),
         | 
| 74 | 
            +
              logo: File.expand_path('../prawn.png', __FILE__),
         | 
| 75 | 
            +
              file_name: 'breakdown_a4.pdf',
         | 
| 76 | 
            +
              page_size: :a4
         | 
| 77 | 
            +
            )
         | 
    
        data/examples/long_invoice.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            #!/usr/bin/env ruby
         | 
| 2 | 
            -
            # This is an example of a  | 
| 2 | 
            +
            # This is an example of a longer invoice.
         | 
| 3 3 |  | 
| 4 4 | 
             
            lib = File.expand_path('../../lib', __FILE__)
         | 
| 5 5 | 
             
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         | 
| @@ -12,7 +12,7 @@ labels = { | |
| 12 12 | 
             
            item = InvoicePrinter::Document::Item.new(
         | 
| 13 13 | 
             
              name: 'Programming',
         | 
| 14 14 | 
             
              quantity: '10',
         | 
| 15 | 
            -
              unit: ' | 
| 15 | 
            +
              unit: 'h',
         | 
| 16 16 | 
             
              price: '$ 60',
         | 
| 17 17 | 
             
              tax: '$ 60',
         | 
| 18 18 | 
             
              amount: '$ 600'
         | 
| @@ -21,7 +21,7 @@ item = InvoicePrinter::Document::Item.new( | |
| 21 21 | 
             
            item2 = InvoicePrinter::Document::Item.new(
         | 
| 22 22 | 
             
              name: 'Consulting',
         | 
| 23 23 | 
             
              quantity: '10',
         | 
| 24 | 
            -
              unit: ' | 
| 24 | 
            +
              unit: 'h',
         | 
| 25 25 | 
             
              price: '$ 30',
         | 
| 26 26 | 
             
              tax: '$ 30',
         | 
| 27 27 | 
             
              amount: '$ 300'
         | 
| @@ -30,7 +30,7 @@ item2 = InvoicePrinter::Document::Item.new( | |
| 30 30 | 
             
            item3 = InvoicePrinter::Document::Item.new(
         | 
| 31 31 | 
             
              name: 'Support',
         | 
| 32 32 | 
             
              quantity: '20',
         | 
| 33 | 
            -
              unit: ' | 
| 33 | 
            +
              unit: 'h',
         | 
| 34 34 | 
             
              price: '$ 15',
         | 
| 35 35 | 
             
              tax: '$ 30',
         | 
| 36 36 | 
             
              amount: '$ 330'
         | 
    
        data/examples/promo.rb
    CHANGED
    
    | @@ -80,6 +80,7 @@ InvoicePrinter.print( | |
| 80 80 | 
             
              document: invoice,
         | 
| 81 81 | 
             
              labels: labels,
         | 
| 82 82 | 
             
              font: File.expand_path('../../assets/fonts/overpass/Overpass-Regular.ttf', __FILE__),
         | 
| 83 | 
            +
              bold_font: File.expand_path('../../assets/fonts/overpass/Overpass-Bold.ttf', __FILE__),
         | 
| 83 84 | 
             
              logo: File.expand_path('../logo.png', __FILE__),
         | 
| 84 85 | 
             
              file_name: 'promo.pdf'
         | 
| 85 86 | 
             
            )
         | 
| @@ -88,6 +89,7 @@ InvoicePrinter.print( | |
| 88 89 | 
             
              document: invoice,
         | 
| 89 90 | 
             
              labels: labels,
         | 
| 90 91 | 
             
              font: File.expand_path('../../assets/fonts/overpass/Overpass-Regular.ttf', __FILE__),
         | 
| 92 | 
            +
              bold_font: File.expand_path('../../assets/fonts/overpass/Overpass-Bold.ttf', __FILE__),
         | 
| 91 93 | 
             
              logo: File.expand_path('../logo.png', __FILE__),
         | 
| 92 94 | 
             
              file_name: 'promo_a4.pdf',
         | 
| 93 95 | 
             
              page_size: :a4
         | 
| @@ -7,10 +7,13 @@ FONTS_FILES = [ | |
| 7 7 | 
             
              'FONTS_LICENSE.txt',
         | 
| 8 8 | 
             
              'assets/fonts/overpass/OFL-1.1.txt',
         | 
| 9 9 | 
             
              'assets/fonts/overpass/Overpass-Regular.ttf',
         | 
| 10 | 
            +
              'assets/fonts/overpass/Overpass-Bold.ttf',
         | 
| 10 11 | 
             
              'assets/fonts/opensans/Apache-2.0.txt',
         | 
| 11 12 | 
             
              'assets/fonts/opensans/OpenSans-Regular.ttf',
         | 
| 13 | 
            +
              'assets/fonts/opensans/OpenSans-Bold.ttf',
         | 
| 12 14 | 
             
              'assets/fonts/roboto/Apache-2.0.txt',
         | 
| 13 15 | 
             
              'assets/fonts/roboto/Roboto-Regular.ttf',
         | 
| 16 | 
            +
              'assets/fonts/roboto/Roboto-Bold.ttf',
         | 
| 14 17 | 
             
              'lib/invoice_printer/fonts.rb'
         | 
| 15 18 | 
             
            ]
         | 
| 16 19 |  | 
    
        data/lib/invoice_printer.rb
    CHANGED
    
    | @@ -15,6 +15,7 @@ Prawn::Font::AFM.hide_m17n_warning = true | |
| 15 15 | 
             
            #   InvoicePrinter.print(
         | 
| 16 16 | 
             
            #     document: invoice,
         | 
| 17 17 | 
             
            #     font: 'path-to-font-file.ttf',
         | 
| 18 | 
            +
            #     bold_font: 'path-to-font-file.ttf',
         | 
| 18 19 | 
             
            #     stamp: 'stamp.jpg',
         | 
| 19 20 | 
             
            #     logo: 'logo.jpg',
         | 
| 20 21 | 
             
            #     file_name: 'invoice.pdf'
         | 
| @@ -65,16 +66,28 @@ module InvoicePrinter | |
| 65 66 | 
             
              # document - InvoicePrinter::Document object
         | 
| 66 67 | 
             
              # labels - labels to override
         | 
| 67 68 | 
             
              # font - font file to use
         | 
| 69 | 
            +
              # bold_font - bold font file to use
         | 
| 68 70 | 
             
              # stamp - stamp & signature (image)
         | 
| 69 71 | 
             
              # logo - logotype (image)
         | 
| 70 72 | 
             
              # background - background (image)
         | 
| 71 73 | 
             
              # page_size - :letter or :a4
         | 
| 72 74 | 
             
              # file_name - output file
         | 
| 73 | 
            -
              def self.print( | 
| 75 | 
            +
              def self.print(
         | 
| 76 | 
            +
                document:,
         | 
| 77 | 
            +
                labels: {},
         | 
| 78 | 
            +
                font: nil,
         | 
| 79 | 
            +
                bold_font: nil,
         | 
| 80 | 
            +
                stamp: nil,
         | 
| 81 | 
            +
                logo: nil,
         | 
| 82 | 
            +
                background: nil,
         | 
| 83 | 
            +
                page_size: :letter,
         | 
| 84 | 
            +
                file_name:
         | 
| 85 | 
            +
              )
         | 
| 74 86 | 
             
                PDFDocument.new(
         | 
| 75 87 | 
             
                  document: document,
         | 
| 76 88 | 
             
                  labels: labels,
         | 
| 77 89 | 
             
                  font: font,
         | 
| 90 | 
            +
                  bold_font: bold_font,
         | 
| 78 91 | 
             
                  stamp: stamp,
         | 
| 79 92 | 
             
                  logo: logo,
         | 
| 80 93 | 
             
                  background: background,
         | 
| @@ -87,15 +100,26 @@ module InvoicePrinter | |
| 87 100 | 
             
              # document - InvoicePrinter::Document object
         | 
| 88 101 | 
             
              # labels - labels to override
         | 
| 89 102 | 
             
              # font - font file to use
         | 
| 103 | 
            +
              # bold_font - bold font file to use
         | 
| 90 104 | 
             
              # stamp - stamp & signature (image)
         | 
| 91 105 | 
             
              # logo - logotype (image)
         | 
| 92 106 | 
             
              # background - background (image)
         | 
| 93 107 | 
             
              # page_size - :letter or :a4
         | 
| 94 | 
            -
              def self.render( | 
| 108 | 
            +
              def self.render(
         | 
| 109 | 
            +
                document:,
         | 
| 110 | 
            +
                labels: {},
         | 
| 111 | 
            +
                font: nil,
         | 
| 112 | 
            +
                bold_font: nil,
         | 
| 113 | 
            +
                stamp: nil,
         | 
| 114 | 
            +
                logo: nil,
         | 
| 115 | 
            +
                background: nil,
         | 
| 116 | 
            +
                page_size: :letter
         | 
| 117 | 
            +
              )
         | 
| 95 118 | 
             
                PDFDocument.new(
         | 
| 96 119 | 
             
                  document: document,
         | 
| 97 120 | 
             
                  labels: labels,
         | 
| 98 121 | 
             
                  font: font,
         | 
| 122 | 
            +
                  bold_font: bold_font,
         | 
| 99 123 | 
             
                  stamp: stamp,
         | 
| 100 124 | 
             
                  logo: logo,
         | 
| 101 125 | 
             
                  background: background,
         | 
| @@ -6,6 +6,7 @@ module InvoicePrinter | |
| 6 6 | 
             
                #
         | 
| 7 7 | 
             
                #  item = InvoicePrinter::Document::Item.new(
         | 
| 8 8 | 
             
                #    name: 'UX consultation',
         | 
| 9 | 
            +
                #    breakdown: "Monday 3h\nTuesday 1h"
         | 
| 9 10 | 
             
                #    variable: 'June 2008',
         | 
| 10 11 | 
             
                #    quantity: '4',
         | 
| 11 12 | 
             
                #    unit: 'hours',
         | 
| @@ -18,6 +19,7 @@ module InvoicePrinter | |
| 18 19 | 
             
                # but this is not enforced.
         | 
| 19 20 | 
             
                class Item
         | 
| 20 21 | 
             
                  attr_reader :name,
         | 
| 22 | 
            +
                              :breakdown,
         | 
| 21 23 | 
             
                              :variable, # for anything required
         | 
| 22 24 | 
             
                              :quantity,
         | 
| 23 25 | 
             
                              :unit,
         | 
| @@ -30,51 +32,55 @@ module InvoicePrinter | |
| 30 32 | 
             
                  class << self
         | 
| 31 33 | 
             
                    def from_json(json)
         | 
| 32 34 | 
             
                      new(
         | 
| 33 | 
            -
                        name: | 
| 35 | 
            +
                        name: json['name'],
         | 
| 36 | 
            +
                        breakdown: json['breakdown'],
         | 
| 34 37 | 
             
                        variable: json['variable'],
         | 
| 35 38 | 
             
                        quantity: json['quantity'],
         | 
| 36 | 
            -
                        unit: | 
| 37 | 
            -
                        price: | 
| 38 | 
            -
                        tax: | 
| 39 | 
            -
                        tax2: | 
| 40 | 
            -
                        tax3: | 
| 41 | 
            -
                        amount: | 
| 39 | 
            +
                        unit: json['unit'],
         | 
| 40 | 
            +
                        price: json['price'],
         | 
| 41 | 
            +
                        tax: json['tax'],
         | 
| 42 | 
            +
                        tax2: json['tax2'],
         | 
| 43 | 
            +
                        tax3: json['tax3'],
         | 
| 44 | 
            +
                        amount: json['amount']
         | 
| 42 45 | 
             
                      )
         | 
| 43 46 | 
             
                    end
         | 
| 44 47 | 
             
                  end
         | 
| 45 48 |  | 
| 46 | 
            -
                  def initialize(name: | 
| 49 | 
            +
                  def initialize(name: nil,
         | 
| 50 | 
            +
                                 breakdown: nil,
         | 
| 47 51 | 
             
                                 variable: nil,
         | 
| 48 52 | 
             
                                 quantity: nil,
         | 
| 49 | 
            -
                                 unit: | 
| 50 | 
            -
                                 price: | 
| 51 | 
            -
                                 tax: | 
| 52 | 
            -
                                 tax2: | 
| 53 | 
            -
                                 tax3: | 
| 54 | 
            -
                                 amount: | 
| 53 | 
            +
                                 unit: nil,
         | 
| 54 | 
            +
                                 price: nil,
         | 
| 55 | 
            +
                                 tax: nil,
         | 
| 56 | 
            +
                                 tax2: nil,
         | 
| 57 | 
            +
                                 tax3: nil,
         | 
| 58 | 
            +
                                 amount: nil)
         | 
| 55 59 |  | 
| 56 | 
            -
                    @name | 
| 60 | 
            +
                    @name = String(name)
         | 
| 61 | 
            +
                    @breakdown = String(breakdown)
         | 
| 57 62 | 
             
                    @variable = String(variable)
         | 
| 58 63 | 
             
                    @quantity = String(quantity)
         | 
| 59 | 
            -
                    @unit | 
| 60 | 
            -
                    @price | 
| 61 | 
            -
                    @tax | 
| 62 | 
            -
                    @tax2 | 
| 63 | 
            -
                    @tax3 | 
| 64 | 
            -
                    @amount | 
| 64 | 
            +
                    @unit = String(unit)
         | 
| 65 | 
            +
                    @price = String(price)
         | 
| 66 | 
            +
                    @tax = String(tax)
         | 
| 67 | 
            +
                    @tax2 = String(tax2)
         | 
| 68 | 
            +
                    @tax3 = String(tax3)
         | 
| 69 | 
            +
                    @amount = String(amount)
         | 
| 65 70 | 
             
                  end
         | 
| 66 71 |  | 
| 67 72 | 
             
                  def to_h
         | 
| 68 73 | 
             
                    {
         | 
| 69 | 
            -
                      'name': | 
| 74 | 
            +
                      'name': @name,
         | 
| 75 | 
            +
                      'breakdown': @breakdown,
         | 
| 70 76 | 
             
                      'variable': @variable,
         | 
| 71 77 | 
             
                      'quantity': @quantity,
         | 
| 72 | 
            -
                      'unit': | 
| 73 | 
            -
                      'price': | 
| 74 | 
            -
                      'tax': | 
| 75 | 
            -
                      'tax2': | 
| 76 | 
            -
                      'tax3': | 
| 77 | 
            -
                      'amount': | 
| 78 | 
            +
                      'unit': @unit,
         | 
| 79 | 
            +
                      'price': @price,
         | 
| 80 | 
            +
                      'tax': @tax,
         | 
| 81 | 
            +
                      'tax2': @tax2,
         | 
| 82 | 
            +
                      'tax3': @tax3,
         | 
| 83 | 
            +
                      'amount': @amount,
         | 
| 78 84 | 
             
                    }
         | 
| 79 85 | 
             
                  end
         | 
| 80 86 |  | 
| @@ -11,6 +11,7 @@ module InvoicePrinter | |
| 11 11 | 
             
              #     document: invoice,
         | 
| 12 12 | 
             
              #     labels: {},
         | 
| 13 13 | 
             
              #     font: 'font.ttf',
         | 
| 14 | 
            +
              #     bold_font: 'bold_font.ttf',
         | 
| 14 15 | 
             
              #     stamp: 'stamp.jpg',
         | 
| 15 16 | 
             
              #     logo: 'example.jpg'
         | 
| 16 17 | 
             
              #   )
         | 
| @@ -20,7 +21,7 @@ module InvoicePrinter | |
| 20 21 | 
             
                class StampFileNotFound < StandardError; end
         | 
| 21 22 | 
             
                class InvalidInput < StandardError; end
         | 
| 22 23 |  | 
| 23 | 
            -
                attr_reader :invoice, :labels, :file_name, :font, :stamp, :logo
         | 
| 24 | 
            +
                attr_reader :invoice, :labels, :file_name, :font, :bold_font, :stamp, :logo
         | 
| 24 25 |  | 
| 25 26 | 
             
                DEFAULT_LABELS = {
         | 
| 26 27 | 
             
                  name: 'Invoice',
         | 
| @@ -66,10 +67,20 @@ module InvoicePrinter | |
| 66 67 | 
             
                  @@labels = DEFAULT_LABELS.merge(labels)
         | 
| 67 68 | 
             
                end
         | 
| 68 69 |  | 
| 69 | 
            -
                def initialize( | 
| 70 | 
            +
                def initialize(
         | 
| 71 | 
            +
                  document: Document.new,
         | 
| 72 | 
            +
                  labels: {},
         | 
| 73 | 
            +
                  font: nil,
         | 
| 74 | 
            +
                  bold_font: nil,
         | 
| 75 | 
            +
                  stamp: nil,
         | 
| 76 | 
            +
                  logo: nil,
         | 
| 77 | 
            +
                  background: nil,
         | 
| 78 | 
            +
                  page_size: :letter
         | 
| 79 | 
            +
                )
         | 
| 70 80 | 
             
                  @document  = document
         | 
| 71 81 | 
             
                  @labels    = merge_custom_labels(labels)
         | 
| 72 82 | 
             
                  @font      = font
         | 
| 83 | 
            +
                  @bold_font = bold_font
         | 
| 73 84 | 
             
                  @stamp     = stamp
         | 
| 74 85 | 
             
                  @logo      = logo
         | 
| 75 86 | 
             
                  @page_size = page_size ? PAGE_SIZES[page_size.to_sym] : PAGE_SIZES[:letter]
         | 
| @@ -94,8 +105,10 @@ module InvoicePrinter | |
| 94 105 | 
             
                    end
         | 
| 95 106 | 
             
                  end
         | 
| 96 107 |  | 
| 97 | 
            -
                  if used? @ | 
| 98 | 
            -
                    use_font(@font)
         | 
| 108 | 
            +
                  if used?(@font) && used?(@bold_font)
         | 
| 109 | 
            +
                    use_font(@font, @bold_font)
         | 
| 110 | 
            +
                  elsif used?(@font)
         | 
| 111 | 
            +
                    use_font(@font, @font)
         | 
| 99 112 | 
             
                  end
         | 
| 100 113 |  | 
| 101 114 | 
             
                  build_pdf
         | 
| @@ -113,11 +126,11 @@ module InvoicePrinter | |
| 113 126 |  | 
| 114 127 | 
             
                private
         | 
| 115 128 |  | 
| 116 | 
            -
                def use_font(font)
         | 
| 117 | 
            -
                  if File.exist?( | 
| 118 | 
            -
                    set_font_from_path( | 
| 129 | 
            +
                def use_font(font, bold_font)
         | 
| 130 | 
            +
                  if File.exist?(font) && File.exist?(bold_font)
         | 
| 131 | 
            +
                    set_font_from_path(font, bold_font)
         | 
| 119 132 | 
             
                  else
         | 
| 120 | 
            -
                    set_builtin_font( | 
| 133 | 
            +
                    set_builtin_font(font)
         | 
| 121 134 | 
             
                  end
         | 
| 122 135 | 
             
                end
         | 
| 123 136 |  | 
| @@ -134,14 +147,14 @@ module InvoicePrinter | |
| 134 147 | 
             
                end
         | 
| 135 148 |  | 
| 136 149 | 
             
                # Add font family in Prawn for a given +font+ file
         | 
| 137 | 
            -
                def set_font_from_path(font)
         | 
| 150 | 
            +
                def set_font_from_path(font, bold_font)
         | 
| 138 151 | 
             
                  font_name = Pathname.new(font).basename
         | 
| 139 152 | 
             
                  @pdf.font_families.update(
         | 
| 140 153 | 
             
                    "#{font_name}" => {
         | 
| 141 154 | 
             
                      normal: font,
         | 
| 142 155 | 
             
                      italic: font,
         | 
| 143 | 
            -
                      bold:  | 
| 144 | 
            -
                      bold_italic:  | 
| 156 | 
            +
                      bold: bold_font,
         | 
| 157 | 
            +
                      bold_italic: bold_font
         | 
| 145 158 | 
             
                    }
         | 
| 146 159 | 
             
                  )
         | 
| 147 160 | 
             
                  @pdf.font(font_name)
         | 
| @@ -708,7 +721,8 @@ module InvoicePrinter | |
| 708 721 | 
             
                def build_items_data(items_params)
         | 
| 709 722 | 
             
                  @document.items.map do |item|
         | 
| 710 723 | 
             
                    line = []
         | 
| 711 | 
            -
                    line << { content: item | 
| 724 | 
            +
                    line << { content: name_cell(item), borders: [:bottom] } if items_params[:names]
         | 
| 725 | 
            +
                    #line << { content: item.name, borders: [:bottom], align: :left } if items_params[:names]
         | 
| 712 726 | 
             
                    line << { content: item.variable, align: :right } if items_params[:variables]
         | 
| 713 727 | 
             
                    line << { content: item.quantity, align: :right } if items_params[:quantities]
         | 
| 714 728 | 
             
                    line << { content: item.unit, align: :right } if items_params[:units]
         | 
| @@ -721,6 +735,27 @@ module InvoicePrinter | |
| 721 735 | 
             
                  end
         | 
| 722 736 | 
             
                end
         | 
| 723 737 |  | 
| 738 | 
            +
                # Display item's name and breakdown if present
         | 
| 739 | 
            +
                def name_cell(item)
         | 
| 740 | 
            +
                  data = if used?(item.breakdown)
         | 
| 741 | 
            +
                    data = [
         | 
| 742 | 
            +
                      [{ content: item.name, padding: [5, 0, 0, 5] }],
         | 
| 743 | 
            +
                      [{ content: item.breakdown, size: 8, padding: [2, 0, 5, 5] }]
         | 
| 744 | 
            +
                    ]
         | 
| 745 | 
            +
             | 
| 746 | 
            +
                    options = {
         | 
| 747 | 
            +
                      cell_style: {
         | 
| 748 | 
            +
                        borders: []
         | 
| 749 | 
            +
                      },
         | 
| 750 | 
            +
                      position: :left
         | 
| 751 | 
            +
                    }
         | 
| 752 | 
            +
             | 
| 753 | 
            +
                    @pdf.make_table(data, options)
         | 
| 754 | 
            +
                  else
         | 
| 755 | 
            +
                    item.name
         | 
| 756 | 
            +
                  end
         | 
| 757 | 
            +
                end
         | 
| 758 | 
            +
             | 
| 724 759 | 
             
                # Include only relevant headers
         | 
| 725 760 | 
             
                def build_items_header(items_params)
         | 
| 726 761 | 
             
                  headers = []
         | 
| @@ -759,52 +794,40 @@ module InvoicePrinter | |
| 759 794 | 
             
                  @pdf.move_down(25)
         | 
| 760 795 |  | 
| 761 796 | 
             
                  items = []
         | 
| 762 | 
            -
                  items << [{ content: "#{@labels[:subtotal]}:#{build_sublabel_for_total_table(:subtotal)}", align: :right }, @document.subtotal] \
         | 
| 763 | 
            -
                    unless @document.subtotal.empty?
         | 
| 764 | 
            -
                  items << [{ content: "#{@labels[:tax]}:#{build_sublabel_for_total_table(:tax)}", align: :right }, @document.tax] \
         | 
| 765 | 
            -
                    unless @document.tax.empty?
         | 
| 766 | 
            -
                  items << [{ content: "#{@labels[:tax2]}:#{build_sublabel_for_total_table(:tax2)}", align: :right }, @document.tax2] \
         | 
| 767 | 
            -
                    unless @document.tax2.empty?
         | 
| 768 | 
            -
                  items << [{ content: "#{@labels[:tax3]}:#{build_sublabel_for_total_table(:tax3)}", align: :right }, @document.tax3] \
         | 
| 769 | 
            -
                    unless @document.tax3.empty?
         | 
| 770 | 
            -
             | 
| 771 | 
            -
                  width = [
         | 
| 772 | 
            -
                    "#{@labels[:subtotal]}#{@document.subtotal}".size,
         | 
| 773 | 
            -
                    "#{@labels[:tax]}#{@document.tax}".size,
         | 
| 774 | 
            -
                    "#{@labels[:tax2]}#{@document.tax2}".size,
         | 
| 775 | 
            -
                    "#{@labels[:tax3]}#{@document.tax3}".size
         | 
| 776 | 
            -
                  ].max * 8
         | 
| 777 797 |  | 
| 778 | 
            -
                   | 
| 779 | 
            -
                     | 
| 780 | 
            -
             | 
| 781 | 
            -
             | 
| 782 | 
            -
                  }
         | 
| 798 | 
            +
                  items << [
         | 
| 799 | 
            +
                    { content: "#{@labels[:subtotal]}:#{build_sublabel_for_total_table(:subtotal)}", align: :left },
         | 
| 800 | 
            +
                    { content: @document.subtotal, align: :right }
         | 
| 801 | 
            +
                  ] unless @document.subtotal.empty?
         | 
| 783 802 |  | 
| 784 | 
            -
                   | 
| 785 | 
            -
                    @ | 
| 786 | 
            -
             | 
| 803 | 
            +
                  items << [
         | 
| 804 | 
            +
                    { content: "#{@labels[:tax]}:#{build_sublabel_for_total_table(:tax)}", align: :left },
         | 
| 805 | 
            +
                    { content:  @document.tax, align: :right }
         | 
| 806 | 
            +
                  ] unless @document.tax.empty?
         | 
| 787 807 |  | 
| 788 | 
            -
                   | 
| 808 | 
            +
                  items << [
         | 
| 809 | 
            +
                    { content: "#{@labels[:tax2]}:#{build_sublabel_for_total_table(:tax2)}", align: :left },
         | 
| 810 | 
            +
                    { content:  @document.tax2, align: :right }
         | 
| 811 | 
            +
                  ] unless @document.tax2.empty?
         | 
| 789 812 |  | 
| 790 | 
            -
                   | 
| 791 | 
            -
                    @ | 
| 792 | 
            -
             | 
| 793 | 
            -
             | 
| 794 | 
            -
                      align: :right,
         | 
| 795 | 
            -
                      style: :bold
         | 
| 796 | 
            -
                    )
         | 
| 813 | 
            +
                  items << [
         | 
| 814 | 
            +
                    { content: "#{@labels[:tax3]}:#{build_sublabel_for_total_table(:tax3)}", align: :left },
         | 
| 815 | 
            +
                    { content:  @document.tax3, align: :right }
         | 
| 816 | 
            +
                  ] unless @document.tax3.empty?
         | 
| 797 817 |  | 
| 798 | 
            -
             | 
| 818 | 
            +
                  items << [
         | 
| 819 | 
            +
                    { content: "\n#{@labels[:total]}:#{build_sublabel_for_total_table(:total)}", align: :left, font_style: :bold, size: 16 },
         | 
| 820 | 
            +
                    { content:  "\n#{@document.total}", align: :right, font_style: :bold, size: 16 }
         | 
| 821 | 
            +
                  ] unless @document.total.empty?
         | 
| 799 822 |  | 
| 800 | 
            -
             | 
| 801 | 
            -
             | 
| 802 | 
            -
             | 
| 803 | 
            -
             | 
| 804 | 
            -
             | 
| 805 | 
            -
             | 
| 806 | 
            -
             | 
| 807 | 
            -
                   | 
| 823 | 
            +
                  options = {
         | 
| 824 | 
            +
                    cell_style: {
         | 
| 825 | 
            +
                      borders: []
         | 
| 826 | 
            +
                    },
         | 
| 827 | 
            +
                    position: :right
         | 
| 828 | 
            +
                  }
         | 
| 829 | 
            +
             | 
| 830 | 
            +
                  @pdf.table(items, options) unless items.empty?
         | 
| 808 831 | 
             
                end
         | 
| 809 832 |  | 
| 810 833 | 
             
                # Return sublabel on a new line or empty string
         | 
    
        data/test/examples_test.rb
    CHANGED
    
    | @@ -4,10 +4,12 @@ require 'test_helper' | |
| 4 4 | 
             
            class ExamplesTest < Minitest::Test
         | 
| 5 5 | 
             
              def setup
         | 
| 6 6 | 
             
                examples_directory = File.expand_path('../../examples', __FILE__)
         | 
| 7 | 
            +
                assets_directory = File.expand_path('../../assets', __FILE__)
         | 
| 7 8 | 
             
                @examples = Dir.glob("#{examples_directory}/*.rb")
         | 
| 8 9 | 
             
                @test_dir = File.absolute_path('./tmp/invoice_printer_examples')
         | 
| 9 10 | 
             
                FileUtils.mkdir_p @test_dir
         | 
| 10 11 | 
             
                FileUtils.copy_entry examples_directory, @test_dir
         | 
| 12 | 
            +
                FileUtils.cp_r assets_directory, File.absolute_path('./tmp/')
         | 
| 11 13 | 
             
              end
         | 
| 12 14 |  | 
| 13 15 | 
             
              def teardown
         | 
    
        data/test/test_ext.rb
    CHANGED
    
    | @@ -101,7 +101,8 @@ module InvoicePrinter | |
| 101 101 | 
             
                  strings << @document.tax2
         | 
| 102 102 | 
             
                  strings << "#{@labels[:tax3]}:"
         | 
| 103 103 | 
             
                  strings << @document.tax3
         | 
| 104 | 
            -
                  strings << "#{@labels[:total]}: | 
| 104 | 
            +
                  strings << "#{@labels[:total]}:"
         | 
| 105 | 
            +
                  strings << @document.total
         | 
| 105 106 | 
             
                  strings
         | 
| 106 107 | 
             
                end
         | 
| 107 108 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: invoice_printer
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.2.0 | 
| 4 | 
            +
              version: 2.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Josef Strzibny
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-06-17 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: json
         | 
| @@ -95,12 +95,16 @@ files: | |
| 95 95 | 
             
            - LICENSE.txt
         | 
| 96 96 | 
             
            - README.md
         | 
| 97 97 | 
             
            - Rakefile
         | 
| 98 | 
            +
            - assets/fonts/opensans/OpenSans-Bold.ttf
         | 
| 99 | 
            +
            - assets/fonts/overpass/Overpass-Bold.ttf
         | 
| 100 | 
            +
            - assets/fonts/roboto/Roboto-Bold.ttf
         | 
| 98 101 | 
             
            - benchmarks/render.yml
         | 
| 99 102 | 
             
            - bin/invoice_printer
         | 
| 100 103 | 
             
            - docs/COMMAND_LINE.md
         | 
| 101 104 | 
             
            - docs/INSTALLATION.md
         | 
| 102 105 | 
             
            - docs/LIBRARY.md
         | 
| 103 106 | 
             
            - docs/SERVER.md
         | 
| 107 | 
            +
            - examples/breakdown.rb
         | 
| 104 108 | 
             
            - examples/clients/node.js
         | 
| 105 109 | 
             
            - examples/complex_invoice.rb
         | 
| 106 110 | 
             
            - examples/czech_invoice.rb
         | 
| @@ -149,11 +153,11 @@ required_ruby_version: !ruby/object:Gem::Requirement | |
| 149 153 | 
             
                  version: '2.4'
         | 
| 150 154 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 151 155 | 
             
              requirements:
         | 
| 152 | 
            -
              - - " | 
| 156 | 
            +
              - - ">="
         | 
| 153 157 | 
             
                - !ruby/object:Gem::Version
         | 
| 154 | 
            -
                  version:  | 
| 158 | 
            +
                  version: '0'
         | 
| 155 159 | 
             
            requirements: []
         | 
| 156 | 
            -
            rubygems_version: 3.2. | 
| 160 | 
            +
            rubygems_version: 3.2.3
         | 
| 157 161 | 
             
            signing_key: 
         | 
| 158 162 | 
             
            specification_version: 4
         | 
| 159 163 | 
             
            summary: Super simple PDF invoicing in pure Ruby
         |