2020-12-29 17:31:57 +01:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
# Generate a downloadable PDF file for the recorded payment schedule
|
|
|
|
class PDF::PaymentSchedule < Prawn::Document
|
|
|
|
require 'stringio'
|
|
|
|
include ActionView::Helpers::NumberHelper
|
|
|
|
include ApplicationHelper
|
|
|
|
|
2021-01-04 18:12:44 +01:00
|
|
|
##
|
|
|
|
# @param payment_schedule {PaymentSchedule}
|
|
|
|
##
|
2020-12-29 17:31:57 +01:00
|
|
|
def initialize(payment_schedule)
|
|
|
|
super(margin: 70)
|
|
|
|
|
|
|
|
# fonts
|
|
|
|
opensans = Rails.root.join('vendor/assets/fonts/OpenSans-Regular.ttf').to_s
|
|
|
|
opensans_bold = Rails.root.join('vendor/assets/fonts/OpenSans-Bold.ttf').to_s
|
|
|
|
opensans_bolditalic = Rails.root.join('vendor/assets/fonts/OpenSans-BoldItalic.ttf').to_s
|
|
|
|
opensans_italic = Rails.root.join('vendor/assets/fonts/OpenSans-Italic.ttf').to_s
|
|
|
|
|
|
|
|
font_families.update(
|
|
|
|
'Open-Sans' => {
|
|
|
|
normal: { file: opensans, font: 'Open-Sans' },
|
|
|
|
bold: { file: opensans_bold, font: 'Open-Sans-Bold' },
|
|
|
|
italic: { file: opensans_italic, font: 'Open-Sans-Oblique' },
|
|
|
|
bold_italic: { file: opensans_bolditalic, font: 'Open-Sans-BoldOblique' }
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
# logo
|
|
|
|
img_b64 = Setting.find_by(name: 'invoice_logo')
|
|
|
|
begin
|
|
|
|
image StringIO.new(Base64.decode64(img_b64.value)), fit: [415, 40]
|
|
|
|
rescue StandardError => e
|
|
|
|
puts "Unable to decode invoice logo from base64: #{e}"
|
|
|
|
end
|
|
|
|
move_down 20
|
|
|
|
font('Open-Sans', size: 10) do
|
|
|
|
# general information
|
|
|
|
text I18n.t('payment_schedules.schedule_reference', REF: payment_schedule.reference), leading: 3
|
|
|
|
text I18n.t('payment_schedules.schedule_issued_on_DATE', DATE: I18n.l(payment_schedule.created_at.to_date))
|
|
|
|
|
|
|
|
# user/organization's information
|
2021-01-04 17:03:44 +01:00
|
|
|
if payment_schedule.invoicing_profile&.organization
|
|
|
|
name = payment_schedule.invoicing_profile.organization.name
|
|
|
|
full_name = "#{name} (#{payment_schedule.invoicing_profile.full_name})"
|
2020-12-29 17:31:57 +01:00
|
|
|
else
|
2021-01-04 17:03:44 +01:00
|
|
|
name = payment_schedule.invoicing_profile.full_name
|
2020-12-29 17:31:57 +01:00
|
|
|
full_name = name
|
|
|
|
end
|
|
|
|
|
2021-01-04 17:03:44 +01:00
|
|
|
address = if payment_schedule.invoicing_profile&.organization&.address
|
|
|
|
payment_schedule.invoicing_profile.organization.address.address
|
|
|
|
elsif payment_schedule.invoicing_profile&.address
|
|
|
|
payment_schedule.invoicing_profile.address.address
|
2020-12-29 17:31:57 +01:00
|
|
|
else
|
|
|
|
''
|
|
|
|
end
|
|
|
|
|
2021-01-04 17:03:44 +01:00
|
|
|
text_box "<b>#{name}</b>\n#{payment_schedule.invoicing_profile.email}\n#{address}",
|
2020-12-29 17:31:57 +01:00
|
|
|
at: [bounds.width - 130, bounds.top - 49],
|
|
|
|
width: 130,
|
|
|
|
align: :right,
|
|
|
|
inline_format: true
|
|
|
|
name = full_name
|
2021-06-24 16:52:47 +02:00
|
|
|
subscription = payment_schedule.payment_schedule_objects.find { |pso| pso.object_type == Subscription.name }.subscription
|
2020-12-29 17:31:57 +01:00
|
|
|
|
|
|
|
# object
|
|
|
|
move_down 25
|
2021-01-04 18:12:44 +01:00
|
|
|
text I18n.t('payment_schedules.object', ITEM: subscription_verbose(subscription, name))
|
2020-12-29 17:31:57 +01:00
|
|
|
|
2021-01-04 18:12:44 +01:00
|
|
|
# details table of the deadlines
|
2020-12-29 17:31:57 +01:00
|
|
|
move_down 20
|
2021-01-04 18:12:44 +01:00
|
|
|
text I18n.t('payment_schedules.deadlines'), leading: 4
|
2020-12-29 17:31:57 +01:00
|
|
|
move_down 2
|
2021-01-04 18:12:44 +01:00
|
|
|
data = [[I18n.t('payment_schedules.deadline_date'), I18n.t('payment_schedules.deadline_amount')]]
|
2020-12-29 17:31:57 +01:00
|
|
|
|
2021-01-04 18:12:44 +01:00
|
|
|
# going through the payment_schedule_items
|
|
|
|
payment_schedule.payment_schedule_items.each do |item|
|
2020-12-29 17:31:57 +01:00
|
|
|
|
|
|
|
price = item.amount.to_i / 100.00
|
2021-01-19 16:47:51 +01:00
|
|
|
date = I18n.l(item.due_date.to_date)
|
2020-12-29 17:31:57 +01:00
|
|
|
|
2021-01-04 18:12:44 +01:00
|
|
|
data += [[date, number_to_currency(price)]]
|
2020-12-29 17:31:57 +01:00
|
|
|
end
|
2021-01-04 18:12:44 +01:00
|
|
|
data += [[I18n.t('payment_schedules.total_amount'), number_to_currency(payment_schedule.total / 100.0)]]
|
2020-12-29 17:31:57 +01:00
|
|
|
|
|
|
|
# display table
|
2021-01-19 16:47:51 +01:00
|
|
|
font_size(8) do
|
|
|
|
table(data, header: true, column_widths: [400, 72], cell_style: { inline_format: true }) do
|
|
|
|
row(0).font_style = :bold
|
|
|
|
column(1).style align: :right
|
|
|
|
row(-1).style align: :right
|
|
|
|
row(-1).background_color = 'E4E4E4'
|
|
|
|
row(-1).font_style = :bold
|
|
|
|
end
|
2020-12-29 17:31:57 +01:00
|
|
|
end
|
|
|
|
|
2021-01-04 18:12:44 +01:00
|
|
|
# payment method
|
2020-12-29 17:31:57 +01:00
|
|
|
move_down 20
|
2021-01-04 18:12:44 +01:00
|
|
|
payment_verbose = _t('payment_schedules.settlement_by_METHOD', METHOD: payment_schedule.payment_method)
|
2021-02-09 15:44:56 +01:00
|
|
|
if payment_schedule.wallet_amount
|
|
|
|
payment_verbose += I18n.t('payment_schedules.settlement_by_wallet',
|
|
|
|
AMOUNT: number_to_currency(payment_schedule.wallet_amount / 100.00))
|
|
|
|
end
|
2020-12-29 17:31:57 +01:00
|
|
|
text payment_verbose
|
|
|
|
|
|
|
|
# important information
|
|
|
|
move_down 40
|
|
|
|
txt = parse_html(Setting.get('invoice_text'))
|
|
|
|
txt.each_line do |line|
|
|
|
|
text line, style: :bold, inline_format: true
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# address and legals information
|
|
|
|
move_down 40
|
|
|
|
txt = parse_html(Setting.get('invoice_legals'))
|
|
|
|
txt.each_line do |line|
|
|
|
|
text line, align: :right, leading: 4, inline_format: true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# factice watermark
|
2021-01-19 16:47:51 +01:00
|
|
|
return unless %w[staging test development].include?(payment_schedule.environment)
|
2020-12-29 17:31:57 +01:00
|
|
|
|
|
|
|
transparent(0.1) do
|
|
|
|
rotate(45, origin: [0, 0]) do
|
2021-05-12 16:58:39 +02:00
|
|
|
image "#{Rails.root}/app/pdfs/data/watermark-#{I18n.default_locale}.png", at: [90, 150]
|
2020-12-29 17:31:57 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def subscription_verbose(subscription, username)
|
|
|
|
subscription_start_at = subscription.expired_at - subscription.plan.duration
|
|
|
|
duration_verbose = I18n.t("duration.#{subscription.plan.interval}", count: subscription.plan.interval_count)
|
2021-01-04 18:12:44 +01:00
|
|
|
I18n.t('payment_schedules.subscription_of_NAME_for_DURATION_starting_from_DATE',
|
2020-12-29 17:31:57 +01:00
|
|
|
NAME: username,
|
|
|
|
DURATION: duration_verbose,
|
|
|
|
DATE: I18n.l(subscription_start_at.to_date))
|
|
|
|
end
|
|
|
|
|
|
|
|
##
|
|
|
|
# Remove every unsupported html tag from the given html text (like <p>, <span>, ...).
|
|
|
|
# The supported tags are <b>, <u>, <i> and <br>.
|
|
|
|
# @param html [String] single line html text
|
|
|
|
# @return [String] multi line simplified html text
|
|
|
|
##
|
|
|
|
def parse_html(html)
|
|
|
|
ActionController::Base.helpers.sanitize(html, tags: %w[b u i br])
|
|
|
|
end
|
|
|
|
end
|