Skip to content

Commit

Permalink
Payor deleted: keep payments and make a note (AgileVentures#798)
Browse files Browse the repository at this point in the history
* record that a payor was deleted in Payment notes

* record the payor was deleted in every payment

* don't delete payments if Company is deleted; record in payment notes

* record deleted User in payment notes; refactor some specs

* deleted time = Time.zone.now; add default specs for PaymentUtility record_deleted_payorinfo_in_payment_notes
  • Loading branch information
weedySeaDragon authored Jun 9, 2020
1 parent f504ef0 commit bf03074
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 20 deletions.
4 changes: 3 additions & 1 deletion app/models/company.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class Company < ApplicationRecord
has_many :users, through: :shf_applications
has_many :events, dependent: :destroy

has_many :payments, dependent: :destroy
has_many :payments, dependent: :nullify
# ^^ need to retain h-branding payment(s) so that the total amount of $ paid to SHF is correct
accepts_nested_attributes_for :payments

has_many :business_categories,
Expand Down Expand Up @@ -220,6 +221,7 @@ def destroy_checks

error_if_has_applications?

record_deleted_payorinfo_in_payment_notes
end


Expand Down
14 changes: 14 additions & 0 deletions app/models/concerns/payment_utility.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ def admin_can_edit_status?

end


# record info about this user in any associated payments so payment history for this user is not lost
def record_deleted_payorinfo_in_payment_notes(payor_class = self.class,
email = self.email,
time_deleted = Time.zone.now)
payments.each do |payment|
payment.note_payor_deleted(payor_class, email, time_deleted)
end
end


# ===========================================================================


# - FIXME how to store this date if/when the member is no longer a current member?
#
class_methods do
Expand Down
13 changes: 13 additions & 0 deletions app/models/payment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ class Payment < ApplicationRecord
PAYMENT_TYPE_MEMBER = 'member_fee'
PAYMENT_TYPE_BRANDING = 'branding_fee'

NOTES_DEFAULT_PAYOR = 'User'
NOTES_UNKNOWN_EMAIL = '<email unknown>'
NOTES_SEPARATOR = '; ' unless defined?(NOTES_SEPARATOR)


# This hash maps a HIPS order status to an SHF payment status.
# The payment values are stored in the DB and exposed to the user.
# (The user is paying a fee to SHF (payment). In order to process that
Expand Down Expand Up @@ -100,4 +105,12 @@ def successfully_completed
notify_observers(self)
end


def note_payor_deleted(payor_type = NOTES_DEFAULT_PAYOR,
payor_email = NOTES_UNKNOWN_EMAIL,
deleted_time = Time.zone.now)
deleted_note = "#{payor_type} #{payor_email} for this payment was deleted on #{deleted_time}"
update(notes: (notes.nil? ? deleted_note : "#{notes}#{NOTES_SEPARATOR}#{deleted_note}") )
end

end
13 changes: 12 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable

before_destroy { self.member_photo = nil } # remove photo file from file system
before_destroy :adjust_related_info_for_destroy

has_one :shf_application, dependent: :destroy
accepts_nested_attributes_for :shf_application, update_only: true
Expand Down Expand Up @@ -296,6 +296,12 @@ def issue_membership_number
end


def adjust_related_info_for_destroy
remove_photo_from_filesystem
record_deleted_payorinfo_in_payment_notes(self.class, email)
end


private


Expand All @@ -305,4 +311,9 @@ def get_next_membership_number
end


# remove the associated member photo from the file system by setting it to nil
def remove_photo_from_filesystem
member_photo = nil
end

end
31 changes: 28 additions & 3 deletions spec/models/company_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@
it { is_expected.to have_many(:events).dependent(:destroy) }
end

describe 'destroy associated records when company is destroyed' do
describe 'destroy or nullify associated records when a Company is destroyed' do

let(:user1) { create(:user) }
let(:user2) { create(:user) }
let(:application1) do
Expand Down Expand Up @@ -129,6 +130,14 @@
pic
end


it 'destroy_checks is called before destory' do
co = create(:company)
expect(co).to receive(:destroy_checks)
co.destroy
end


it 'addresses' do
expect { company_3_addrs }.to change(Address, :count).by(3)
expect { company_3_addrs.destroy }.to change(Address, :count).by(-3)
Expand All @@ -148,14 +157,30 @@
expect { company_3_addrs.destroy }.to change(Ckeditor::Picture, :count).by(-2)
end

it 'payments' do
it 'payments are NOT deleted if a company is deleted; company_id is set to nil' do
# create the payments
brand_pymt1
brand_pymt2
expect(company_3_addrs.payments.count).to eq 2
expect { company_3_addrs.destroy }.to change(Payment, :count).by(-2)
expect(Payment.where(company_id: nil).count).to eq 0

expect { company_3_addrs.destroy }.not_to change(Payment, :count)
expect(Payment.where(company_id: nil).count).to eq 2
end

end


describe 'destroy_checks' do

it 'calls record_deleted_payorinfo_in_payment_notes' do
co = create(:company)
expect(co).to receive(:record_deleted_payorinfo_in_payment_notes)
co.destroy
end
end


describe 'events update management' do

around(:each) do |example|
Expand Down
49 changes: 49 additions & 0 deletions spec/models/concerns/payment_utility_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -461,4 +461,53 @@
end

end


describe 'record_deleted_payorinfo_in_payment_notes' do

describe 'defaults' do

it 'payor class: class of the payor' do
u = member_paid_up
payment1 = u.payments.first
expect(payment1).to receive(:note_payor_deleted).with(u.class, anything, anything)

u.record_deleted_payorinfo_in_payment_notes
end

it 'email: email for the payor' do
u = member_paid_up
payment1 = u.payments.first
expect(payment1).to receive(:note_payor_deleted).with(anything, u.email, anything)

u.record_deleted_payorinfo_in_payment_notes
end

it 'time_deleted: Time.zone.now' do
u = member_paid_up
payment1 = u.payments.first
tz_now = Time.zone.now

Timecop.freeze(tz_now) do
expect(payment1).to receive(:note_payor_deleted).with(anything, anything, tz_now)
u.record_deleted_payorinfo_in_payment_notes
end
end
end

it 'each payment records info in notes about this payor' do
u = build(:user)

membership_payment = build(:membership_fee_payment)
hbranding_payment = build(:h_branding_fee_payment)

allow(u).to receive(:payments).and_return([membership_payment, hbranding_payment])

expect(membership_payment).to receive(:note_payor_deleted)
expect(hbranding_payment).to receive(:note_payor_deleted)

u.record_deleted_payorinfo_in_payment_notes
end

end
end
60 changes: 60 additions & 0 deletions spec/models/payment_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,64 @@
end

end


describe 'note_payor_deleted' do

let(:time_pattern) { '\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d UTC' }

describe "deleted payor info = <payor_type> <payor_email> for this payment was deleted on <deleted_time>" do

context 'defaults' do

it 'payor_type: User' do
expect(subject.notes).to be_nil
subject.note_payor_deleted
expect(subject.notes).to match(/^User /)
end

it 'payor_email: <email unknown>' do
expect(subject.notes).to be_nil
subject.note_payor_deleted
expect(subject.notes).to match(/^\w+ <email unknown>/)
end

it 'deleted_time: Time.zone.now' do
expect(subject.notes).to be_nil
tz_now = Time.zone.now
Timecop.freeze(tz_now) do
subject.note_payor_deleted
expect(subject.notes).to match(/#{tz_now}$/)
end
end
end

it 'record the info passed in' do
expect(subject.notes).to be_nil
time_deleted = Time.now.utc
subject.note_payor_deleted('Some class', 'some-email@example.com', time_deleted)
expect(subject.notes).to match(/^Some class some-email@example.com for this payment was deleted on #{time_deleted}/)
end
end

context 'notes is nil' do
it 'notes is now just the deleted payor info' do
expect(subject.notes).to be_nil
subject.note_payor_deleted
expect(subject.notes).to match(/^User <email unknown> for this payment was deleted on #{time_pattern}/)
end
end

context 'notes is not nil' do
it 'the deleted payor info is appended to the existing notes' do
orig_notes = 'original notes'
subject.update(notes: orig_notes)
expect(subject.notes).to eq orig_notes

subject.note_payor_deleted
expect(subject.notes).to match(/^#{orig_notes}; User <email unknown> for this payment was deleted on #{time_pattern}/)
end

end
end
end
49 changes: 34 additions & 15 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,11 +216,13 @@
it 'member_photo' do
expect(user_with_member_photo.member_photo).not_to be_nil
expect(user_with_member_photo.member_photo.exists?).to be true
member_photo = user_with_member_photo.member_photo

user_with_member_photo.destroy

expect(user_with_member_photo.destroyed?).to be true
expect(user_with_member_photo.member_photo.exists?).to be false
expect(member_photo.exists?).to be_falsey
expect(user_with_member_photo.destroyed?).to be_truthy
expect(user_with_member_photo.member_photo.exists?).to be_falsey
end

context 'membership application' do
Expand All @@ -235,25 +237,42 @@
end
end

context 'nullify user_id in associated payment records' do
it 'membership payments' do
user_id = user.id
context 'payments are NOT deleted if a user is deleted' do

expect { member_payment1; member_payment2 }.to change(Payment, :count).by(2)
context 'membership payments' do

expect { user.destroy }.not_to change(Payment, :count)
expect(Payment.find_by_user_id(user_id)).to be_nil
before(:each) do
# create the payments
member_payment1
member_payment2
end

it 'user (id) is set to nil' do
user_id = user.id
expect(Payment.where(user_id: nil).count).to eq 0
expect { user.destroy }.not_to change(Payment, :count)

expect(Payment.find_by_user_id(user_id)).to be_nil
expect(Payment.where(user_id: nil).count).to eq 2
end
end

it 'h-branding payments' do
company_id = complete_co.id
user_id = user.id

expect { branding_payment1; branding_payment2 }.to change(Payment, :count).by(2)
context 'h-branding (h-markt licensing) payments' do

it 'user (id) is set to nil' do
company_id = complete_co.id
user_id = user.id

expect { user.destroy }.not_to change(Payment, :count)
expect(Payment.find_by_company_id(company_id)).not_to be_nil
expect(Payment.find_by_user_id(user_id)).to be_nil
# create the payments
expect { branding_payment1; branding_payment2 }.to change(Payment, :count).by(2)
expect(Payment.where(user_id: nil).count).to eq 0

expect { user.destroy }.not_to change(Payment, :count)
expect(Payment.find_by_company_id(company_id)).not_to be_nil
expect(Payment.find_by_user_id(user_id)).to be_nil
expect(Payment.where(user_id: nil).count).to eq 2
end
end
end
end
Expand Down

0 comments on commit bf03074

Please sign in to comment.