ruby-invoice 0.0.1
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 +7 -0
- data/lib/invoice.rb +338 -0
- metadata +60 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: b07c2a4f05598ceece3360ab252c8a179e462ebd
|
|
4
|
+
data.tar.gz: 99894ecfa8c8e25bd2ad84e2cbb1d4f6991d683f
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d5b815de2fb29b10736fa1e01ac3d9a34dbd8ecc1e18a88ab76545511d0cd6e62c86db81e63ee0f8d619f19b407233fe0370fc1ec9ae8332aa97e41d1e0e35b0
|
|
7
|
+
data.tar.gz: 8eb1cbe96a54b2fa92bd50fcbd1bad2a6bb4744c4ff26d2c00e53279ce3ed5a52793c0c98580c1bbea116898fef17fdbe1ff0022e2621eee9d40c95a67a6e095
|
data/lib/invoice.rb
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
require 'prawn'
|
|
2
|
+
|
|
3
|
+
class Invoice < Prawn::Document
|
|
4
|
+
FONT_NAME = "Helvetica"
|
|
5
|
+
|
|
6
|
+
def initialize(invoice_number)
|
|
7
|
+
super()
|
|
8
|
+
@name = nil
|
|
9
|
+
@language = :es
|
|
10
|
+
@address = nil
|
|
11
|
+
@dni = nil
|
|
12
|
+
@phone = nil
|
|
13
|
+
@activity = nil
|
|
14
|
+
@vat = 0
|
|
15
|
+
@detail_page_items = nil
|
|
16
|
+
@items = []
|
|
17
|
+
@currency = "$"
|
|
18
|
+
@invoice_number = invoice_number
|
|
19
|
+
@company_name = nil
|
|
20
|
+
@company_address = nil
|
|
21
|
+
@company_phone = nil
|
|
22
|
+
@companany_dni = nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def generate
|
|
26
|
+
|
|
27
|
+
draw_proforma_box # Invoice box in the upper right corner
|
|
28
|
+
insert_logo
|
|
29
|
+
render_company_info # Company information Right to the logo
|
|
30
|
+
render_reception_box # Reception box in the lower left corner
|
|
31
|
+
render_client_information
|
|
32
|
+
render_items_table
|
|
33
|
+
add_items_to_table
|
|
34
|
+
|
|
35
|
+
unless @detail_page_items.nil?
|
|
36
|
+
render_detail_page
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
self
|
|
40
|
+
save
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#########################
|
|
44
|
+
### RENDERING TABLE ###
|
|
45
|
+
#########################
|
|
46
|
+
|
|
47
|
+
def render_client_information
|
|
48
|
+
normal_font
|
|
49
|
+
move_down 40
|
|
50
|
+
text languages(:receptor)
|
|
51
|
+
text_box languages(:table_date), :at => [305, 605]
|
|
52
|
+
move_down 10
|
|
53
|
+
text languages(:table_address)
|
|
54
|
+
move_down 10
|
|
55
|
+
text languages(:table_dni)
|
|
56
|
+
text_box languages(:table_phone), :at => [160, 556]
|
|
57
|
+
text_box languages(:table_activity), :at => [340, 556]
|
|
58
|
+
render_lines
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def render_items_table
|
|
62
|
+
text_box languages(:item_title), :at => [0, 510], :width => 50, :align => :center
|
|
63
|
+
text_box languages(:description_title), :at => [50, 510], :width => 250, :align => :center
|
|
64
|
+
text_box languages(:quantity_title), :at => [300, 510], :width => 70, :align => :center
|
|
65
|
+
text_box languages(:price_title), :at => [370, 510], :width => 80, :align => :center
|
|
66
|
+
text_box languages(:value_title), :at => [450, 510], :width => 100, :align => :center
|
|
67
|
+
text_box languages(:subtotal_title), :at => [300, 50], :width => 150, :align => :center
|
|
68
|
+
text_box languages(:vat_title), :at => [300, 32], :width => 150, :align => :center
|
|
69
|
+
text_box languages(:total_title), :at => [300, 14], :width => 150, :align => :center
|
|
70
|
+
stroke_rounded_rectangle [0, 520], 550, 450, 10
|
|
71
|
+
stroke_rounded_rectangle [300, 60], 250, 65, 10
|
|
72
|
+
stroke_line [50, 520], [50, 70]
|
|
73
|
+
stroke_line [300, 520], [300, 70]
|
|
74
|
+
stroke_line [370, 520], [370, 70]
|
|
75
|
+
stroke_line [450, 520], [450, 70]
|
|
76
|
+
stroke_line [0, 495], [550, 495]
|
|
77
|
+
stroke_line [450, 60], [450, -5]
|
|
78
|
+
stroke_line [300, 37], [550, 37]
|
|
79
|
+
stroke_line [300, 18], [550, 18]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def calculate_total_values(values)
|
|
83
|
+
text_box @currency, :at => [450, 50], :width => 20, :align => :center
|
|
84
|
+
text_box add_delimiter(values.inject(:+).round(2).to_s), :at => [470, 50], :width => 80, :align => :center
|
|
85
|
+
text_box @currency, :at => [450, 32], :width => 20, :align => :center
|
|
86
|
+
text_box add_delimiter((values.inject(:+)*@vat/100).round(2).to_s), :at => [470, 32], :width => 80, :align => :center
|
|
87
|
+
text_box @currency, :at => [450, 14], :width => 20, :align => :center
|
|
88
|
+
text_box add_delimiter((values.inject(:+)*(100 + @vat)/100).round(2).to_s), :at => [470, 14], :width => 80, :align => :center
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def add_items_to_table
|
|
92
|
+
if @items.count <= 10 && @items.count > 0
|
|
93
|
+
i = 0
|
|
94
|
+
spacing = 40
|
|
95
|
+
@items.each do |item|
|
|
96
|
+
text_box (i + 1).to_s, :at => [0, 480 - i*spacing], :width => 50, :align => :center
|
|
97
|
+
text_box item[:description], :at => [50, 480 - i*spacing], :width => 250, :align => :center
|
|
98
|
+
text_box add_delimiter(item[:quantity].to_s), :at => [300, 480 - i*spacing], :width => 70, :align => :center
|
|
99
|
+
text_box @currency, :at => [370, 480 - i*spacing], :width => 20, :align => :center
|
|
100
|
+
text_box add_delimiter(item[:price].to_s), :at => [390, 480 - i*spacing], :width => 60, :align => :center
|
|
101
|
+
text_box @currency, :at => [450, 480 - i*spacing], :width => 20, :align => :center
|
|
102
|
+
text_box add_delimiter((item[:price]*item[:quantity]).round(2).to_s), :at => [470, 480 - i*spacing], :width => 80, :align => :center
|
|
103
|
+
i+=1
|
|
104
|
+
end
|
|
105
|
+
values = @items.map {|x| x[:price]*x[:quantity]}
|
|
106
|
+
calculate_total_values values
|
|
107
|
+
else
|
|
108
|
+
p "Max. 10 items, Min. 0 items"
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def render_lines
|
|
113
|
+
if @language == :es
|
|
114
|
+
line [70, 593], [295, 593]
|
|
115
|
+
line [350, 593], [550, 593]
|
|
116
|
+
line [71, 569], [550, 569]
|
|
117
|
+
line [37, 545], [150, 545]
|
|
118
|
+
line [230, 545], [330, 545]
|
|
119
|
+
line [375, 545], [550, 545]
|
|
120
|
+
elsif @language == :en
|
|
121
|
+
line [40, 593], [295, 593]
|
|
122
|
+
line [338, 593], [550, 593]
|
|
123
|
+
line [62, 569], [550, 569]
|
|
124
|
+
line [25, 545], [150, 545]
|
|
125
|
+
line [208, 545], [330, 545]
|
|
126
|
+
line [398, 545], [550, 545]
|
|
127
|
+
end
|
|
128
|
+
stroke
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def insert_logo
|
|
132
|
+
image "img/logo.png"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def draw_proforma_box
|
|
136
|
+
title_font
|
|
137
|
+
stroke_rectangle [360, 730], 190, 90
|
|
138
|
+
text_box languages(:title), :width => 190, :align => :center, :at => [360, 705]
|
|
139
|
+
text_box languages(:number) + ": #{@invoice_number.to_s}", :width => 190, :align => :center, :at => [360, 680]
|
|
140
|
+
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#########################
|
|
144
|
+
#### COMPANY INFO ####
|
|
145
|
+
#########################
|
|
146
|
+
|
|
147
|
+
def render_company_info
|
|
148
|
+
mini_font
|
|
149
|
+
text_box @company_name, :at => [140, 706], :width => 200, :align => :left
|
|
150
|
+
text_box @company_address, :at => [140, 693], :width => 200, :align => :left
|
|
151
|
+
text_box @company_phone, :at => [140, 680], :width => 200, :align => :left
|
|
152
|
+
text_box @company_dni, :at => [140, 667], :width => 200, :align => :left
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def add_company_info(name, address, phone, dni = nil)
|
|
156
|
+
@company_name = name
|
|
157
|
+
@company_address = address
|
|
158
|
+
@company_phone = phone
|
|
159
|
+
@company_dni = dni
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
#########################
|
|
163
|
+
### RECEPTION BOX ###
|
|
164
|
+
#########################
|
|
165
|
+
|
|
166
|
+
def render_reception_box
|
|
167
|
+
mini_font
|
|
168
|
+
text_box languages(:receptor_name), :at => [10, 56], :width => 200, :align => :left
|
|
169
|
+
text_box languages(:receptor_date), :at => [10, 36], :width => 200, :align => :left
|
|
170
|
+
text_box languages(:receptor_signature), :at => [10, 16], :width => 200, :align => :left
|
|
171
|
+
draw_reception_lines
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def draw_reception_lines
|
|
175
|
+
if @language == :es
|
|
176
|
+
stroke_line [52, 47], [280, 47]
|
|
177
|
+
stroke_line [42, 27], [280, 27]
|
|
178
|
+
stroke_line [41, 7], [280, 7]
|
|
179
|
+
elsif @language == :en
|
|
180
|
+
stroke_line [42, 47], [280, 47]
|
|
181
|
+
stroke_line [35, 27], [280, 27]
|
|
182
|
+
stroke_line [61, 7], [280, 7]
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
#########################
|
|
187
|
+
##### DETAIL PAGE #####
|
|
188
|
+
#########################
|
|
189
|
+
|
|
190
|
+
def render_detail_page
|
|
191
|
+
start_new_page
|
|
192
|
+
insert_logo
|
|
193
|
+
title_font
|
|
194
|
+
move_down 30
|
|
195
|
+
text languages(:detail_page_title)
|
|
196
|
+
normal_font
|
|
197
|
+
@detail_page_items.map {|x| text x}
|
|
198
|
+
move_down 10
|
|
199
|
+
text "------------"
|
|
200
|
+
move_down 10
|
|
201
|
+
text "Total: #{@detail_page_items.count.to_s}"
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def add_details(items)
|
|
205
|
+
@detail_page_items = items
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
#########################
|
|
210
|
+
#### CONFIGURATION ####
|
|
211
|
+
#########################
|
|
212
|
+
|
|
213
|
+
def set_language(language)
|
|
214
|
+
@language = language.to_sym
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def set_client_info(name = nil, address = nil, dni = nil, phone = nil, activity = nil)
|
|
218
|
+
@name = name
|
|
219
|
+
@address = address
|
|
220
|
+
@dni = dni
|
|
221
|
+
@phone = phone
|
|
222
|
+
@activity = activity
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def set_tax(vat)
|
|
226
|
+
@vat = vat
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def add_item(description, quantity, price)
|
|
230
|
+
@items << {
|
|
231
|
+
:description => description[0..84],
|
|
232
|
+
:quantity => quantity,
|
|
233
|
+
:price => price.round(3)
|
|
234
|
+
}
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def set_currency(currency)
|
|
238
|
+
@currency = currency
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
#########################
|
|
242
|
+
##### DELIMITER #####
|
|
243
|
+
#########################
|
|
244
|
+
|
|
245
|
+
def add_delimiter(number)
|
|
246
|
+
number.reverse.gsub(/(\d{3})(?=\d)/, '\\1,').reverse
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
#########################
|
|
250
|
+
##### LANGUAGES #####
|
|
251
|
+
#########################
|
|
252
|
+
|
|
253
|
+
def languages(content)
|
|
254
|
+
hash = Hash.new
|
|
255
|
+
hash[:es] = {
|
|
256
|
+
:greet => "Estimados señores #{@name}",
|
|
257
|
+
:title => "Factura Proforma",
|
|
258
|
+
:number => "Número",
|
|
259
|
+
:receptor => "SEÑOR(ES): #{@name}",
|
|
260
|
+
:table_date => "FECHA: #{Time.now.strftime('%d/%m/%Y')}",
|
|
261
|
+
:table_address => "DIRECCIÓN: #{@address}",
|
|
262
|
+
:table_dni => "R.U.T.: #{@dni}",
|
|
263
|
+
:table_phone => "TELÉFONO: #{@phone}",
|
|
264
|
+
:table_activity => "GIRO: #{@activity}",
|
|
265
|
+
:item_title => "ITEM",
|
|
266
|
+
:description_title => "DESCRIPCIÓN",
|
|
267
|
+
:quantity_title => "CANTIDAD",
|
|
268
|
+
:price_title => "PRECIO",
|
|
269
|
+
:value_title => "VALOR",
|
|
270
|
+
:subtotal_title => "SUBTOTAL",
|
|
271
|
+
:vat_title => "IMPUESTO #{@vat}%",
|
|
272
|
+
:total_title => "TOTAL",
|
|
273
|
+
:detail_page_title => "Detalles",
|
|
274
|
+
:receptor_name => "Nombre:",
|
|
275
|
+
:receptor_date => "Fecha:",
|
|
276
|
+
:receptor_signature => "Firma:"
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
hash[:en] = {
|
|
280
|
+
:greet => "Dear Mr. #{@name}",
|
|
281
|
+
:title => "Proforma Invoice",
|
|
282
|
+
:number => "number",
|
|
283
|
+
:receptor => "NAME: #{@name}",
|
|
284
|
+
:table_date => "DATE: #{Time.now.strftime('%d/%m/%Y')}",
|
|
285
|
+
:table_address => "ADDRESS: #{@address}",
|
|
286
|
+
:table_dni => "DNI: #{@dni}",
|
|
287
|
+
:table_phone => "PHONE: #{@phone}",
|
|
288
|
+
:table_activity => "ACTIVITY: #{@activity}",
|
|
289
|
+
:item_title => "ITEM",
|
|
290
|
+
:description_title => "DESCRIPTION",
|
|
291
|
+
:quantity_title => "QUANTITY",
|
|
292
|
+
:price_title => "PRICE",
|
|
293
|
+
:value_title => "VALUE",
|
|
294
|
+
:subtotal_title => "SUBTOTAL",
|
|
295
|
+
:vat_title => "TAX #{@vat}%",
|
|
296
|
+
:total_title => "TOTAL",
|
|
297
|
+
:detail_page_title => "Details",
|
|
298
|
+
:receptor_name => "Name:",
|
|
299
|
+
:receptor_date => "Date:",
|
|
300
|
+
:receptor_signature => "Signature:"
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
hash[@language][content]
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
#########################
|
|
308
|
+
###### FONTS ########
|
|
309
|
+
#########################
|
|
310
|
+
|
|
311
|
+
def title_font
|
|
312
|
+
font FONT_NAME, style: :bold
|
|
313
|
+
font_size 18
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def mini_font
|
|
317
|
+
font FONT_NAME, style: :bold
|
|
318
|
+
font_size 10
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
def normal_font
|
|
322
|
+
font FONT_NAME, style: :normal
|
|
323
|
+
font_size 12
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
#########################
|
|
327
|
+
###### SAVE ########
|
|
328
|
+
#########################
|
|
329
|
+
|
|
330
|
+
def save
|
|
331
|
+
invoices_folder = "invoices/"
|
|
332
|
+
Dir.mkdir(invoices_folder) unless File.directory?(invoices_folder)
|
|
333
|
+
filename = invoices_folder + @name.downcase.gsub(" ", '-') + "-#{@invoice_number}" + ".pdf"
|
|
334
|
+
render_file filename
|
|
335
|
+
return filename
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ruby-invoice
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Nicolas Kipreos
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2014-07-21 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: prawn
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - '='
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: 1.0.0
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - '='
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: 1.0.0
|
|
27
|
+
description: Ruby Invoice is a gem special for generating invoices in a simple and
|
|
28
|
+
fast way.
|
|
29
|
+
email: nkipreos@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/invoice.rb
|
|
35
|
+
homepage: http://github.com/nkipreos/ruby_invoices
|
|
36
|
+
licenses:
|
|
37
|
+
- Beerware
|
|
38
|
+
metadata: {}
|
|
39
|
+
post_install_message:
|
|
40
|
+
rdoc_options: []
|
|
41
|
+
require_paths:
|
|
42
|
+
- lib
|
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
|
+
requirements:
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: '0'
|
|
53
|
+
requirements: []
|
|
54
|
+
rubyforge_project:
|
|
55
|
+
rubygems_version: 2.2.2
|
|
56
|
+
signing_key:
|
|
57
|
+
specification_version: 4
|
|
58
|
+
summary: Invoicing Gem Ideal for Commercial Rails Applications
|
|
59
|
+
test_files: []
|
|
60
|
+
has_rdoc:
|