/lib/vesr/prawn/esr_recipe.rb

https://github.com/raskhadafi/vesr · Ruby · 149 lines · 109 code · 27 blank · 13 comment · 4 complexity · f5b2003007215cfe96f6bb376bb4426c MD5 · raw file

  1. require 'action_view/helpers/translation_helper'
  2. require 'action_view/helpers'
  3. require 'vesr/reference_builder'
  4. require 'vesr/validation_digit_calculator'
  5. module Prawn
  6. module EsrRecipe
  7. include ActionView::Helpers::TranslationHelper
  8. def draw_account_detail(bank, sender, print_payment_for)
  9. if bank
  10. text bank.vcard.full_name
  11. text bank.vcard.postal_code + " " + bank.vcard.locality
  12. end
  13. text " "
  14. if print_payment_for
  15. text I18n::translate(:biller, :scope => "activerecord.attributes.invoice")
  16. else
  17. text " "
  18. end
  19. text " "
  20. draw_address sender.vcard
  21. end
  22. def draw_account(account)
  23. bounding_box [cm2pt(2.6), bounds.top - cm2pt(3.4)], :width => cm2pt(2.5) do
  24. font_size 9 do
  25. text account.pc_id
  26. end
  27. end
  28. end
  29. def draw_amount(amount)
  30. font_size 10 do
  31. bounding_box [0, bounds.top - cm2pt(4.2)], :width => cm2pt(3.6) do
  32. text sprintf('%.0f', amount.floor), :align => :right, :character_spacing => 1
  33. end
  34. bounding_box [cm2pt(4.7), bounds.top - cm2pt(4.2)], :width => cm2pt(1) do
  35. text sprintf('%02.0f', amount * 100 % 100), :character_spacing => 1
  36. end
  37. end
  38. end
  39. # VESR form
  40. # =========
  41. def esr_recipe(invoice, account, sender, print_payment_for)
  42. bounding_box [cm2pt(0.4), cm2pt(9.6)], :width => cm2pt(5) do
  43. indent cm2pt(0.4) do
  44. draw_account_detail(account.bank, sender, print_payment_for)
  45. end
  46. draw_account(account)
  47. draw_amount(invoice.balance.currency_round)
  48. bounding_box [cm2pt(0.4), bounds.top - cm2pt(5.2)], :width => cm2pt(5) do
  49. text esr9_reference(invoice, account), :size => 7
  50. text " "
  51. draw_address invoice.customer.vcard
  52. end
  53. end
  54. bounding_box [cm2pt(6.4), cm2pt(9.6)], :width => cm2pt(5) do
  55. draw_account_detail(account.bank, sender, print_payment_for)
  56. draw_account(account)
  57. draw_amount(invoice.balance.currency_round)
  58. end
  59. font_size 10 do
  60. character_spacing 1.1 do
  61. draw_text esr9_reference(invoice, account), :at => [cm2pt(12.7), cm2pt(6.8)]
  62. end
  63. end
  64. bounding_box [cm2pt(12.7), cm2pt(5.5)], :width => cm2pt(7.5) do
  65. draw_address(invoice.customer.vcard)
  66. end
  67. # ESR-Reference
  68. if ::Rails.root.join('data/ocrb10.ttf').exist?
  69. ocr_font = ::Rails.root.join('data/ocrb10.ttf')
  70. else
  71. ocr_font = "Helvetica"
  72. ::Rails.logger.warn("No ocrb10.ttf found for ESR reference in #{::Rails.root.join('data')}!")
  73. end
  74. font ocr_font, :size => 11 do
  75. character_spacing 0.5 do
  76. draw_text esr9(invoice, account), :at => [cm2pt(6.7), cm2pt(1.7)]
  77. end
  78. end
  79. end
  80. def draw_esr(invoice, account, sender, print_payment_for = true)
  81. float do
  82. canvas do
  83. font 'Helvetica', :size => 8 do
  84. esr_recipe(invoice, account, sender, print_payment_for)
  85. end
  86. end
  87. end
  88. end
  89. private
  90. # ESR helpers
  91. def esr9(invoice, esr_account)
  92. esr9_build(invoice.balance.currency_round, invoice, esr_account.pc_id, esr_account.esr_id)
  93. end
  94. def esr9_reference(invoice, esr_account)
  95. esr_number = VESR::ReferenceBuilder.call(invoice.customer.id, invoice.id, esr_account.esr_id)
  96. esr9_format VESR::ValidationDigitCalculator.call(esr_number)
  97. end
  98. def esr9_build(esr_amount, invoice, biller_id, esr_id)
  99. # 01 is type 'Einzahlung in CHF'
  100. amount_string = "01#{sprintf('%011.2f', esr_amount).delete('.')}"
  101. id_string = VESR::ReferenceBuilder.call(invoice.customer.id, invoice.id, esr_id)
  102. biller_string = esr9_format_account_id(biller_id)
  103. "#{VESR::ValidationDigitCalculator.call(amount_string)}>#{VESR::ValidationDigitCalculator.call(id_string)}+ #{biller_string}>"
  104. end
  105. def esr9_format(reference_code)
  106. # Drop all leading zeroes
  107. reference_code.gsub!(/^0*/, '')
  108. # Group by 5 digit blocks, beginning at the right side
  109. reference_code.reverse.gsub(/(.....)/, '\1 ').reverse
  110. end
  111. # Formats an account number for ESR
  112. #
  113. # Account numbers for ESR should have the following format:
  114. # XXYYYYYYZ, where the number of digits is fixed. We support
  115. # providing the number in the format XX-YYYY-Z which is more
  116. # common in written communication.
  117. def esr9_format_account_id(account_id)
  118. (pre, main, post) = account_id.split('-')
  119. sprintf('%02i%06i%1i', pre.to_i, main.to_i, post.to_i)
  120. end
  121. end
  122. end