Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions app/controllers/invoices_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ def show
# Authorize for authenticated access (integer ID), skip for token-based access
authorize @invoice, :show? unless token_based_access

# Hide navbar when generating PDF
@show_navigationbar = params[:pdf].blank?
@show_extras = params[:pdf].blank?

respond_to do |format|
format.html
format.pdf { render_invoice_pdf }
Expand Down Expand Up @@ -93,16 +97,14 @@ def permitted_attributes
params.require(:invoice).permit(%i[user_id activity_id name_override email_override rows], rows_attributes: %i[name amount price])
end

def render_invoice_pdf # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def render_invoice_pdf
token_based_access = !integer_id?(params[:id])
authorize @invoice, :download? unless token_based_access

html = render_to_string(
template: 'invoices/show',
formats: [:html],
layout: 'pdf'
)
pdf = Grover.new(html).to_pdf
# Use token-based URL for unauthenticated Grover access
url = invoice_url(@invoice.token, pdf: true, only_path: false)
pdf = Grover.new(url).to_pdf
send_data pdf, filename: "Factuur-#{@invoice.human_id}.pdf", type: 'application/pdf', disposition: 'attachment'
rescue StandardError => e
Rails.logger.error "Failed to generate PDF for invoice #{@invoice.id}: #{e.message}"
Expand All @@ -113,4 +115,5 @@ def render_invoice_pdf # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
redirect_to invoice_path(@invoice)
end
end
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
end
9 changes: 3 additions & 6 deletions app/mailers/invoice_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ def invoice_mail(invoice) # rubocop:disable Metrics/AbcSize, Metrics/MethodLengt
end

begin
html = render_to_string(
template: 'invoices/show',
formats: [:html],
layout: 'pdf'
)
pdf = Grover.new(html).to_pdf
# Use token-based URL for unauthenticated Grover access
url = url_for(controller: 'invoices', action: 'show', id: invoice.token, pdf: true, only_path: false)
pdf = Grover.new(url).to_pdf
Comment on lines +13 to +15
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new URL-based PDF attachment generation lacks test coverage. Since the codebase has comprehensive test coverage for controllers, this change should include tests that verify the PDF attachment is correctly generated and attached to the email, including tests for error handling when PDF generation fails.

Copilot uses AI. Check for mistakes.
attachments["#{invoice.human_id}.pdf"] = pdf
rescue StandardError => e
Rails.logger.error "Failed to generate PDF attachment for invoice #{invoice.id}: #{e.message}"
Expand Down
4 changes: 3 additions & 1 deletion app/views/invoices/show.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<%= Rails.application.config.x.company_kvk %>
</td>
</tr>
<% if current_user&.treasurer? %>
<tr>
<th scope="row">
Status
Expand All @@ -60,10 +61,11 @@
<% end %>
</td>
</tr>
<% end %>
</tbody>
</table>

<% unless @invoice.paid? %>
<% if !@invoice.paid? && Rails.application.config.x.mollie_api_key.present? %>
<%= link_to pay_invoice_url @invoice.token do %>
<button class="col-sm-3 offset-sm-9 btn btn-primary">Betalen</button>
Comment on lines +68 to 70
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compound condition can be simplified for better readability. Instead of using the negation operator with unless, consider using a positive condition with if. The current change from unless @invoice.paid? to if !@invoice.paid? && Rails.application.config.x.mollie_api_key.present? could be written more idiomatically as if @invoice.unpaid? && Rails.application.config.x.mollie_api_key.present? or keep the unless pattern consistent.

Suggested change
<% if !@invoice.paid? && Rails.application.config.x.mollie_api_key.present? %>
<%= link_to pay_invoice_url @invoice.token do %>
<button class="col-sm-3 offset-sm-9 btn btn-primary">Betalen</button>
<% if Rails.application.config.x.mollie_api_key.present? %>
<% unless @invoice.paid? %>
<%= link_to pay_invoice_url @invoice.token do %>
<button class="col-sm-3 offset-sm-9 btn btn-primary">Betalen</button>
<% end %>

Copilot uses AI. Check for mistakes.
<% end %>
Expand Down
37 changes: 0 additions & 37 deletions app/views/layouts/pdf.html.erb

This file was deleted.

45 changes: 18 additions & 27 deletions config/initializers/grover.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
# Grover Global Configuration
#
# Use this to set up shared configuration options for your entire application.
# Any of the configuration options shown here can also be applied to single
# models by passing arguments to the Grover.new call.
#
# To learn more, check out the README:
# https://github.com/Studiosity/grover

Grover.configure do |config|
options = {
format: 'A4',
config.options = {
viewport: {
width: 794, # A4 width in pixels at 96 DPI (210mm)
height: 1123 # Starting height, will expand as needed
},
emulate_media: 'screen',
print_background: true,
prefer_css_page_size: false,
display_url: "https://#{Rails.application.config.x.sofia_host}"
executable_path: Rails.env.development? ? nil : '/usr/bin/chromium',
launch_args: if Rails.env.development?
[]
else
[
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--disable-software-rasterizer'
]
end
}

unless Rails.env.development?
options[:executable_path] = '/usr/bin/chromium'
options[:launch_args] = [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--disable-software-rasterizer',
'--hide-scrollbars'
]
end

config.options = options
end