From 817c680c28f42aa51c02d7267dd0213e45e7ec64 Mon Sep 17 00:00:00 2001 From: Viehlieb <3feuerba@informatik.uni-hamburg.de> Date: Thu, 23 Dec 2021 01:50:06 +0100 Subject: [PATCH] add mailer relevant files, add pdf relevant files and confgurations for invoice generation and sending --- .../concerns/send_group_order_invoice_pdf.rb | 12 ++ app/documents/group_order_invoice_pdf.rb | 142 ++++++++++++++++++ app/jobs/notify_group_order_invoice_job.rb | 10 ++ app/mailers/mailer.rb | 18 +++ .../mailer/group_order_invoice.text.haml | 1 + 5 files changed, 183 insertions(+) create mode 100644 app/controllers/concerns/send_group_order_invoice_pdf.rb create mode 100644 app/documents/group_order_invoice_pdf.rb create mode 100644 app/jobs/notify_group_order_invoice_job.rb create mode 100644 app/views/mailer/group_order_invoice.text.haml diff --git a/app/controllers/concerns/send_group_order_invoice_pdf.rb b/app/controllers/concerns/send_group_order_invoice_pdf.rb new file mode 100644 index 00000000..913a4347 --- /dev/null +++ b/app/controllers/concerns/send_group_order_invoice_pdf.rb @@ -0,0 +1,12 @@ +module Concerns::SendGroupOrderInvoicePdf + extend ActiveSupport::Concern + + protected + + def send_group_order_invoice_pdf group_order_invoice + invoice_data = group_order_invoice.load_data_for_invoice + invoice_data[:title] = "Rechnung für " + invoice_data[:supplier] # TODO Internationalise und load_data rausschmeißen + pdf = GroupOrderInvoicePdf.new group_order_invoice.load_data_for_invoice + send_data pdf.to_pdf, filename: pdf.filename, type: 'application/pdf' + end +end diff --git a/app/documents/group_order_invoice_pdf.rb b/app/documents/group_order_invoice_pdf.rb new file mode 100644 index 00000000..13856330 --- /dev/null +++ b/app/documents/group_order_invoice_pdf.rb @@ -0,0 +1,142 @@ +class GroupOrderInvoicePdf < RenderPDF + def filename + I18n.t('documents.group_order_invoice_pdf.filename', :number => @options[:invoice_number]) + '.pdf' + end + + def title + I18n.t('documents.group_order_invoice_pdf.title', :supplier => @options[:supplier]) + end + + def body + contact = FoodsoftConfig[:contact].symbolize_keys + ordergroup = @options[:ordergroup] + + # From paragraph + bounding_box [margin_box.right - 200, margin_box.top-20], width: 200 do + text I18n.t('documents.group_order_invoice_pdf.invoicer') + move_down 7 + text FoodsoftConfig[:name], size: fontsize(9), align: :left + move_down 5 + text contact[:street], size: fontsize(9), align: :left + move_down 5 + text "#{contact[:zip_code]} #{contact[:city]}", size: fontsize(9), align: :left + move_down 5 + unless contact[:phone].blank? + text "#{Supplier.human_attribute_name :phone}: #{contact[:phone]}", size: fontsize(9), align: :left + move_down 5 + end + unless contact[:email].blank? + text "#{Supplier.human_attribute_name :email}: #{contact[:email]}", size: fontsize(9), align: :left + end + move_down 5 + text I18n.t('documents.group_order_invoice_pdf.tax_number', :number => @options[:tax_number]), size: fontsize(9), align: :left + end + + + # Receiving Ordergroup + bounding_box [margin_box.left, margin_box.top - 20], width: 200 do + text I18n.t('documents.group_order_invoice_pdf.invoicee') + move_down 7 + text I18n.t('documents.group_order_invoice_pdf.ordergroup.name', ordergroup: ordergroup.name.to_s ), size: fontsize(9) + move_down 5 + if ordergroup.contact_address + text I18n.t('documents.group_order_invoice_pdf.ordergroup.contact_address', contact_address: ordergroup.contact_address.to_s ), size: fontsize(9) + move_down 5 + end + if ordergroup.contact_phone + text I18n.t('documents.group_order_invoice_pdf.ordergroup.contact_phone', contact_phone: ordergroup.contact_phone.to_s ), size: fontsize(9) + move_down 5 + end + end + + #invoice Date and nnvoice number + bounding_box [margin_box.right - 200, margin_box.top - 150], width: 200 do + text I18n.t('documents.group_order_invoice_pdf.invoice_date', invoice_date: @options[:invoice_date].strftime(I18n.t('date.formats.default'))), align: :left + move_down 5 + text I18n.t('documents.group_order_invoice_pdf.invoice_number', invoice_number: @options[:invoice_number]), align: :left + end + + move_down 15 + + # kind of the "body" of the invoice + text I18n.t('documents.group_order_invoice_pdf.payment_method', payment_method: @options[:payment_method]) + move_down 15 + text I18n.t('documents.group_order_invoice_pdf.table_headline') + move_down 5 + + #------------- Table Data ----------------------- + total_gross = 0 + total_net = 0 + # Articles + + tax_hash_net = Hash.new(0) #for summing up article net prices grouped into vat percentage + tax_hash_gross = Hash.new(0) #same here with gross prices + + group_order = GroupOrder.find(@options[:group_order].id) + marge = FoodsoftConfig[:price_markup] + + # data table looks different when price_markup > 0 + if marge == 0 + data = [I18n.t('documents.group_order_invoice_pdf.no_price_markup_rows')] + else + data = [I18n.t('documents.group_order_invoice_pdf.price_markup_rows', marge: marge)] + end + goa_tax_hash = GroupOrderArticle.where(group_order_id: group_order.id).find_each.group_by {|oat| oat.order_article.price.tax} + goa_tax_hash.each do |tax, group_order_articles| + group_order_articles.each do |goa| + # if no unit is received, nothing is to be charged + next if goa.result.to_i == 0 + order_article = goa.order_article + goa_total_net = goa.result * order_article.price.price + goa_total_gross = goa.result * order_article.price.gross_price + data << [order_article.article.name, + goa.result.to_i, + number_to_currency(order_article.price.price), + number_to_currency(goa_total_net), + tax.to_s + '%', + number_to_currency(goa.total_price)] + tax_hash_net[tax.to_i] += goa_total_net + tax_hash_gross[tax.to_i] += goa_total_gross + total_net += goa_total_net + total_gross += goa_total_gross + end + end + + # Two separate tables for sum and individual data + # article information + data + table data, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table| + table.header = true + table.position= :center + table.cells.border_width = 1 + table.cells.border_color = '666666' + + table.row(0).column(1).width = 40 + table.row(0).border_bottom_width = 2 + table.columns(1).align = :right + table.columns(1..6).align = :right + end + + sum = [] + sum << [nil, nil, nil, nil, I18n.t('documents.group_order_invoice_pdf.sum_to_pay_net'), number_to_currency(total_net)] + tax_hash_net.keys.each do |tax| + sum << [nil,nil,nil,nil, I18n.t('documents.group_order_invoice_pdf.tax_included', tax: tax), number_to_currency(tax_hash_gross[tax] - tax_hash_net[tax])] + end + unless marge == 0 + sum << [nil, nil, nil, nil, I18n.t('documents.group_order_invoice_pdf.markup_included', marge: marge), number_to_currency(total_gross * marge/100.0)] + end + end_sum = total_gross * (1 + marge/100.0) + sum << [nil, nil, nil, nil, I18n.t('documents.group_order_invoice_pdf.sum_to_pay_gross'), number_to_currency(end_sum)] + # table for sum + table sum, position: :right, cell_style: { size: fontsize(8), overflow: :shrink_to_fit } do |table| + sum.length.times do |count| + table.row(count).columns(0..5).borders = [] + end + table.row(sum.length-1).columns(0..4).borders = [] + table.row(sum.length-1).border_bottom_width = 2 + table.row(sum.length-1).columns(5).borders = [:bottom] + + end + + move_down 15 + end +end diff --git a/app/jobs/notify_group_order_invoice_job.rb b/app/jobs/notify_group_order_invoice_job.rb new file mode 100644 index 00000000..1a17fe9a --- /dev/null +++ b/app/jobs/notify_group_order_invoice_job.rb @@ -0,0 +1,10 @@ +class NotifyGroupOrderInvoiceJob < ApplicationJob + def perform(group_order_invoice) + ordergroup = group_order_invoice.group_order.ordergroup + ordergroup.users.each do |user| + Mailer.deliver_now_with_user_locale user do + Mailer.group_order_invoice(group_order_invoice, user) + end + end + end +end diff --git a/app/mailers/mailer.rb b/app/mailers/mailer.rb index 40a8d1de..ae99e08c 100644 --- a/app/mailers/mailer.rb +++ b/app/mailers/mailer.rb @@ -51,6 +51,19 @@ class Mailer < ActionMailer::Base subject: I18n.t('mailer.welcome.subject') end + # Sends automatically generated invoicesfor group orders to ordergroup members + def group_order_invoice(group_order_invoice, user) + @user = user + @group_order_invoice = group_order_invoice + @group_order = group_order_invoice.group_order + @supplier = @group_order.order.supplier.name + @group = @group_order.ordergroup + add_group_order_invoice_attachments(group_order_invoice) + mail to: user, + subject: I18n.t('mailer.group_order_invoice.subject', group: @group.name, supplier: @supplier) + end + + # Sends order result for specific Ordergroup def order_result(user, group_order) @order = group_order.order @@ -168,6 +181,11 @@ class Mailer < ActionMailer::Base attachments['order.csv'] = OrderCsv.new(order, options).to_csv end + def add_group_order_invoice_attachments(group_order_invoice) + attachment_name = group_order_invoice.name + '.pdf' + attachments[attachment_name] = GroupOrderInvoicePdf.new(group_order_invoice.load_data_for_invoice).to_pdf + end + # separate method to allow plugins to mess with the text def additonal_welcome_text(user) end diff --git a/app/views/mailer/group_order_invoice.text.haml b/app/views/mailer/group_order_invoice.text.haml new file mode 100644 index 00000000..75948fbe --- /dev/null +++ b/app/views/mailer/group_order_invoice.text.haml @@ -0,0 +1 @@ += raw t '.text', group: @group.name, supplier: @supplier , foodcoop: FoodsoftConfig[:name]