Skip to content

Reminder mails for not billed times in past month for order responsibles (64086) #263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion app/controllers/accounting_posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class AccountingPostsController < CrudController
self.permitted_attrs = [:closed, :offered_hours, :offered_rate, :offered_total,
:remaining_hours, :portfolio_item_id, :service_id, :billable,
:description_required, :ticket_required, :from_to_times_required,
:meal_compensation,
:meal_compensation, :billing_reminder_active,
{ work_item_attributes: %i[name shortname description] }]

helper_method :order
Expand Down
20 changes: 20 additions & 0 deletions app/jobs/not_billed_times_reminder_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

# Copyright (c) 2006-2022, Puzzle ITC GmbH. This file is part of
# PuzzleTime and licensed under the Affero General Public License version 3
# or later. See the COPYING file at the top-level directory or at
# https://github.com/puzzle/puzzletime.

class NotBilledTimesReminderJob < CronJob
self.cron_expression = '0 5 10 * *'

def perform
Employee.active_employed_last_month.each do |employee|
accounting_posts = employee.managed_orders
.collect(&:accounting_posts)
.flatten
.filter { |ap| ap.billing_reminder_active == true }
EmployeeMailer.not_billed_times_reminder_mail(employee).deliver_now if accounting_posts.any?(&:unbilled_billable_times_exist_in_past_month?)
end
end
end
9 changes: 9 additions & 0 deletions app/mailers/employee_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,13 @@ def worktime_commit_reminder_mail(employee)
subject: 'PuzzleTime Zeiten freigeben'
)
end

def not_billed_times_reminder_mail(employee)
@employee = employee

mail(
to: "#{employee.firstname} #{employee.lastname} <#{employee.email}>",
subject: 'Erinnerung: Noch nicht verrechnete PuzzleTime Zeiten'
)
end
end
8 changes: 8 additions & 0 deletions app/models/accounting_post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ def propagate_closed!
work_item.propagate_closed!(order.status.closed? || closed?)
end

def unbilled_billable_times_exist_in_past_month?
work_item.worktimes
.in_period(Period.parse('-1m'))
.where(billable: true)
.where(invoice_id: nil)
.present?
end

private

def derive_offered_fields
Expand Down
1 change: 1 addition & 0 deletions app/views/accounting_posts/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,4 @@
.col-md-2
.help-block.col-md-5
Die Einstellungen zur Beschreibung, Ticket oder Von-Bis-Zeiten können nicht geändert werden, da bereits Leistungen ohne diese Angaben erfasst wurden.
= f.labeled_input_field :billing_reminder_active, html_options = {caption: 'Erinnerung bei unverrechneten Leistungen senden', title: "Am 10. Tag des Monats wird eine Mail an den/die Auftragsverantwortliche:n gesendet, wenn im Vormonat verrechenbare Leistungen auf diese Position gebucht wurden, die keiner Rechnung zugewiesen sind", data: {toggle: :tooltip}}
16 changes: 16 additions & 0 deletions app/views/employee_mailer/not_billed_times_reminder_mail.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
%h1.h3{:style => "box-sizing: border-box; margin: 0.67em 0; font-family: inherit; font-weight: 400; line-height: 1.1; color: inherit; margin-top: 20px; font-size: 24px; margin-bottom: 20px;"}
Copy link

Choose a reason for hiding this comment

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

[HAML-Lint] reported by reviewdog 🐶
[W] InlineStyles: Do not use inline style attributes

Hallo
= @employee.firstname
%div{:style => "box-sizing: border-box;"}
Copy link

Choose a reason for hiding this comment

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

[HAML-Lint] reported by reviewdog 🐶
[W] InlineStyles: Do not use inline style attributes

.lead
Beim einem der Aufträge, bei welchen du Auftragsverantwortliche:r bist, wurden im vergangenen Monat verrechenbare Leistungen gebucht, welche noch keiner Rechnung zugeteilt wurden.
%br
Bitte überprüfe die Leistungen im
= link_to 'Verrechnungs-Controlling', root_url
%br
.lead
Liebe Grüsse
%br
Dein PuzzleTime
%br
Möchtest du zu einer Buchungsposition künftig keine Erinnerungsmail mehr erhalten, deaktiviere in den Einstellungen der Position die Checkbox "Erinnerung bei unverrechneten Leistungen senden".
10 changes: 10 additions & 0 deletions app/views/employee_mailer/not_billed_times_reminder_mail.text.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Hallo <%= @employee.firstname %>

Beim einem der Aufträge, bei welchen du Auftragsverantwortliche:r bist, wurden im vergangenen Monat verrechenbare Leistungen gebucht, welche noch keiner Rechnung zugeteilt wurden.

Bitte überprüfe die Leistungen im 'Verrechnungs-Controlling' im PuzzleTime.

Möchtest du zu einer Buchungsposition künftig keine Erinnerungsmail mehr erhalten, deaktiviere in den Einstellungen der Position die Checkbox "Erinnerung bei unverrechneten Leistungen senden".

Liebe Grüsse
Dein PuzzleTime
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

class AddBillingReminderActiveToAccountingPosts < ActiveRecord::Migration[7.1]
def change
add_column :accounting_posts, :billing_reminder_active, :boolean, default: true, null: false
end
end
3 changes: 2 additions & 1 deletion db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2025_02_19_080518) do
ActiveRecord::Schema[7.1].define(version: 2025_05_01_075712) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"

Expand All @@ -35,6 +35,7 @@
t.boolean "closed", default: false, null: false
t.integer "service_id"
t.boolean "meal_compensation", default: false, null: false
t.boolean "billing_reminder_active", default: true, null: false
t.index ["portfolio_item_id"], name: "index_accounting_posts_on_portfolio_item_id"
t.index ["service_id"], name: "index_accounting_posts_on_service_id"
t.index ["work_item_id"], name: "index_accounting_posts_on_work_item_id"
Expand Down
42 changes: 42 additions & 0 deletions test/mailers/employee_mailer_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

require 'test_helper'

class EmployeeMailerTest < ActionMailer::TestCase
attr_reader :order, :accounting_post1, :accounting_post2

setup do
@order = Fabricate(:order,
responsible: employees(:next_year_pablo))
@accounting_post1 = Fabricate(:accounting_post,
work_item: Fabricate(:work_item, parent_id: order.work_item_id),
offered_hours: 100,
offered_rate: 100,
billing_reminder_active: true)
@accounting_post2 = Fabricate(:accounting_post,
work_item: Fabricate(:work_item, parent_id: order.work_item_id),
offered_hours: 100,
offered_rate: 0,
billing_reminder_active: false)
end

test 'sends a reminder for an order responsible with active employment' do
order_responsible = employees(:next_year_pablo)
Fabricate(:ordertime, work_item: accounting_post1.work_item, employee: employees(:long_time_john), hours: 5, billable: true, work_date: Period.parse('-1m').end_date)

assert_emails 1 do
NotBilledTimesReminderJob.new.perform
end
mail = ActionMailer::Base.deliveries.last

assert_equal [order_responsible.email], mail.to
end

test 'setting `billing_reminder_active: false` deactivates mails for an accounting_post' do
Fabricate(:ordertime, work_item: accounting_post2.work_item, employee: employees(:long_time_john), hours: 7, billable: true, work_date: Period.parse('-1m').end_date)

assert_emails 0 do
NotBilledTimesReminderJob.new.perform
end
end
end
5 changes: 5 additions & 0 deletions test/mailers/previews/employee_mailer_preview.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ def worktime_commit_reminder_mail
employee = Employee.new(email: '[email protected]', firstname: 'Peter', lastname: 'Puzzler')
EmployeeMailer.worktime_commit_reminder_mail(employee)
end

def not_billed_times_reminder_mail
employee = Employee.new(email: '[email protected]', firstname: 'Peter', lastname: 'Puzzler')
EmployeeMailer.not_billed_times_reminder_mail(employee)
end
end