ruby-invoice 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|