forked from spree-contrib/spree_print_invoice
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbookkeeping_document.rb
More file actions
153 lines (134 loc) · 4.3 KB
/
Copy pathbookkeeping_document.rb
File metadata and controls
153 lines (134 loc) · 4.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
module Spree
class BookkeepingDocument < ActiveRecord::Base
PERSISTED_ATTRS = [
:firstname,
:lastname,
:email,
:total,
:number
]
def self.ransackable_attributes(auth_object = nil)
["created_at", "email", "firstname", "id", "id_value", "lastname", "number", "printable_id", "printable_type", "template", "total", "updated_at"]
end
# Spree::BookkeepingDocument cares about creating PDFs. Whenever it needs to know
# anything about the document to send to the view, it asks a view object.
#
# +printable+ should be an Object, such as Spree::Order or Spree::Shipment.
# template should be a string, such as "invoice" or "packaging_slip"
#
belongs_to :printable, polymorphic: true
validates :printable, :template, presence: true
validates *PERSISTED_ATTRS, presence: true, if: -> { self.persisted? }
scope :invoices, -> { where(template: 'invoice') }
before_create :copy_view_attributes
after_save :after_save_actions
# An instance of Spree::Printable::#{YourModel}::#{YourTemplate}Presenter
#
def view
@_view ||= view_class.new(printable)
end
def date
created_at.to_date
end
def template_name
"spree/printables/#{single_lower_case_name(printable.class.name)}/#{template}"
end
# If the document is called from the view with some method it doesn't know,
# just call the view object. It should know.
def method_missing(method_name, *args, &block)
if view.respond_to? method_name
view.send(method_name, *args, &block)
else
super
end
end
def document_type
"#{printable_type.demodulize.tableize.singularize}_#{template}"
end
# Returns the given template as pdf binary suitable for Rails send_data
#
# If the file is already present it returns this
# else it generates a new file, stores and returns this.
#
# You can disable the pdf file generation with setting
#
# Spree::PrintInvoice::Config.store_pdf to false
#
def pdf
if Spree::PrintInvoice::Config.store_pdf
send_or_create_pdf
else
render_pdf
end
end
# = The PDF file_name
#
def file_name
@_file_name ||= "#{template}-D#{id}-N#{number}.pdf"
end
# = PDF file path
#
def file_path
@_file_path ||= Rails.root.join(storage_path, "#{file_name}")
end
# = PDF storage folder path for given template name
#
# Configure the storage path with +Spree::PrintInvoice::Config.storage_path+
#
# Each template type gets it own pluralized folder inside
# of +Spree::PrintInvoice::Config.storage_path+
#
# == Example:
#
# storage_path('invoice') => "tmp/pdf_prints/invoices"
#
# Creates the folder if it's not present yet.
#
def storage_path
storage_path = Rails.root.join(Spree::PrintInvoice::Config.storage_path, template.pluralize)
FileUtils.mkdir_p(storage_path)
storage_path
end
# Renders the prawn template for give template name in context of ActionView.
#
# Prawn templates need to be placed in the correct folder. For example, for a PDF from
# a Spree::Order with the invoice template, it would be
# the +app/views/spree/printables/order/invoices+ folder.
#
# Assigns +@doc+ instance variable
#
def render_pdf
ApplicationController.render(
template: template_name,
formats: [:pdf],
assigns: { doc: self }
)
end
private
def copy_view_attributes
PERSISTED_ATTRS.each do |attr|
send("#{attr}=", view.send(attr))
end
end
# For a Spree::Order printable and an "invoice" template,
# you would get "spree/documents/order/invoice_view"
# --> Spree::Printables::Order::InvoiceView
#
def view_class
@_view_class ||= "#{template_name}_view".classify.constantize
end
def single_lower_case_name(class_string)
@_single_lower_class_name ||= class_string.demodulize.tableize.singularize
end
# Sends stored pdf for given template from disk.
#
# Renders and stores it if it's not yet present.
#
def send_or_create_pdf
unless File.exist?(file_path)
File.open(file_path, 'wb') { |f| f.puts render_pdf }
end
IO.binread(file_path)
end
end
end