Skip to content

Commit

Permalink
Extend abo roles on invoice payment (#1565)
Browse files Browse the repository at this point in the history
  • Loading branch information
njaeggi committed Jan 30, 2025
1 parent 5fae738 commit c0b8d15
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 0 deletions.
41 changes: 41 additions & 0 deletions app/domain/invoices/abo_magazin/abonnent_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# frozen_string_literal: true

# Copyright (c) 2025, Schweizer Alpen-Club. This file is part of
# hitobito_sac_cas 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/hitobito/hitobito_sac_cas

class Invoices::AboMagazin::AbonnentManager
attr_reader :person, :group

ABONNENT_ROLE_TYPE = "Group::AboMagazin::Abonnent"

def initialize(person, group)
@person = person
@group = group
end

def update_abonnent_status
ActiveRecord::Base.transaction do
if abonnent_role.present?
extend_role_by_one_year(abonnent_role)
elsif expired_abonnent_role.present?
extend_role_by_one_year(expired_abonnent_role)
end
end
end

private

def abonnent_role
person.roles.where(type: ABONNENT_ROLE_TYPE).first
end

def expired_abonnent_role
person.roles.with_inactive.where(type: ABONNENT_ROLE_TYPE, end_on: 1.year.ago..Time.zone.today).first
end

def extend_role_by_one_year(role)
role.update!(end_on: role.end_on + 1.year)
end
end
34 changes: 34 additions & 0 deletions app/jobs/invoices/abo_magazin/invoice_payed_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

# Copyright (c) 2025, Schweizer Alpen-Club. This file is part of
# hitobito_sac_cas 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/hitobito/hitobito_sac_cas.

class Invoices::AboMagazin::InvoicePayedJob < BaseJob
self.parameters = [:person_id, :group_id]

def initialize(person_id, group_id)
super()
@person_id = person_id
@group_id = group_id
end

def perform
abonnent_manager.update_abonnent_status if person && group
end

private

def abonnent_manager
Invoices::AboMagazin::AbonnentManager.new(person, group)
end

def person
@person ||= Person.find(@person_id)
end

def group
@group ||= Group.find(@group_id)
end
end
49 changes: 49 additions & 0 deletions app/models/external_invoice/abo_magazin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

# Copyright (c) 2025, Schweizer Alpen-Club. This file is part of
# hitobito_sac_cas 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/hitobito/hitobito_sac_cas

# == Schema Information
#
# Table name: external_invoices
#
# id :bigint not null, primary key
# abacus_sales_order_key :integer
# issued_at :date
# link_type :string(255)
# sent_at :date
# state :string(255) default("draft"), not null
# total :decimal(12, 2) default(0.0), not null
# type :string(255) not null
# year :integer
# created_at :datetime not null
# updated_at :datetime not null
# link_id :bigint
# person_id :bigint not null
#
# Indexes
#
# index_external_invoices_on_link (link_type,link_id)
# index_external_invoices_on_person_id (person_id)
#
class ExternalInvoice::AboMagazin < ExternalInvoice
after_update :handle_state_change_to_payed

def title
I18n.t("invoices.sac_memberships.title", year: year)
end

private

def handle_state_change_to_payed
if state_changed_to_payed?
Invoices::AboMagazin::InvoicePayedJob.new(person.id, link.id).enqueue!
end
end

def state_changed_to_payed?
saved_change_to_state? && state == "payed"
end
end
2 changes: 2 additions & 0 deletions config/locales/wagon.de.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,8 @@ de:
cannot_set_main_person: Melde dich bei der Geschäftsstelle um den Familienrechnungsempfänger ändern zu lassen

invoices:
abo_magazin:
title: Rechnung Die Alpen %{year}
errors:
data_quality_error: "Die Person hat Datenqualitätsprobleme, daher wurde keine Rechnung erstellt."
create_subject_failed: "Probleme beim Übermitteln der Personendaten"
Expand Down
44 changes: 44 additions & 0 deletions spec/domain/invoices/abo_magazin/abonnent_manager_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# frozen_string_literal: true

# Copyright (c) 2025, Schweizer Alpen-Club. This file is part of
# hitobito_sac_cas 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/hitobito/hitobito_sac_cas

require "spec_helper"

describe Invoices::AboMagazin::AbonnentManager do
let(:abonnent) { roles(:abonnent_alpen) }
let(:abonnent_person) { people(:abonnent) }
let(:die_alpen) { groups(:abo_die_alpen) }

context "person is abonnent already" do
subject { described_class.new(abonnent_person, die_alpen) }

it "adds one year to current end_on" do
end_on_before = abonnent.end_on

subject.update_abonnent_status

expect(abonnent.reload.end_on).to eq(end_on_before + 1.year)
end
end

context "person has expired abonnent role" do
subject { described_class.new(abonnent_person, die_alpen) }

it "does nothing if previous role expired over a year ago" do
abonnent.update_column(:end_on, 2.years.ago)
end_on_before = abonnent.end_on
subject.update_abonnent_status
expect(abonnent.reload.end_on).to eq end_on_before
end

it "sets end_on to one year after previous role end_on" do
abonnent.update_column(:end_on, 30.days.ago)
end_on_before = abonnent.end_on
subject.update_abonnent_status
expect(abonnent.reload.end_on).to eq(end_on_before + 1.year)
end
end
end
21 changes: 21 additions & 0 deletions spec/jobs/invoices/abo_magazin/invoice_payed_job_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

# Copyright (c) 2025, Schweizer Alpen-Club. This file is part of
# hitobito_sac_cas 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/hitobito/hitobito_sac_cas

require "spec_helper"

describe Invoices::AboMagazin::InvoicePayedJob do
let(:group) { groups(:abo_die_alpen) }
let(:person) { people(:abonnent) }

subject(:job) { described_class.new(person.id, group.id) }

it "executes membership manager update membership status" do
expect_any_instance_of(Invoices::AboMagazin::AbonnentManager).to receive(:update_abonnent_status)

job.perform
end
end
58 changes: 58 additions & 0 deletions spec/models/external_invoice/abo_magazin_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

# Copyright (c) 2025, Schweizer Alpen-Club. This file is part of
# hitobito_sac_cas 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/hitobito/hitobito_sac_cas

require "spec_helper"

describe ExternalInvoice::AboMagazin do
let(:date) { Date.new(2023, 1, 1) }
let(:person) { people(:abonnent) }
let(:group) { groups(:abo_die_alpen) }

describe "after_update callback" do
let(:external_invoice) { ExternalInvoice::AboMagazin.create!(state: :draft, person: person, link: group) }

context "state changes to payed" do
it "enques job" do
expect_enqueued_job do
external_invoice.update!(state: :payed)
end
end
end

context "when the state does not change to payed" do
it "does not queue the job" do
expect_no_enqueued_job do
external_invoice.update!(state: :draft)
external_invoice.update!(state: :open)
end
end
end

context "when state is already payed" do
let(:payed_external_invoice) { ExternalInvoice::AboMagazin.create!(state: :payed, person: person, link: group) }

it "does not queue the job" do
expect_no_enqueued_job do
payed_external_invoice.update!(person: people(:familienmitglied))
payed_external_invoice.update!(state: :open)
end
end
end

def expect_no_enqueued_job
expect do
yield
end.not_to change { Delayed::Job.where("handler like '%Invoices::AboMagazin::InvoicePayedJob%'").count }
end

def expect_enqueued_job
expect do
yield
end.to change { Delayed::Job.where("handler like '%Invoices::AboMagazin::InvoicePayedJob%'").count }
end
end
end

0 comments on commit c0b8d15

Please sign in to comment.