Skip to content
This repository was archived by the owner on Feb 20, 2020. It is now read-only.
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
19 changes: 1 addition & 18 deletions app/controllers/allocations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,13 @@ def upload_review
api :POST, '/allocations?membership_id&amount'
def create
group = Group.find(allocation_params[:group_id])
user = User.find(allocation_params[:user_id])
amount = allocation_params[:amount]
notify = allocation_params[:notify]
params[:allocation].delete(:notify)
from_group_account = allocation_params[:from_group_account]
params[:allocation].delete(:from_group_account)
render status: 403, nothing: true and return unless current_user.is_admin_for?(group)

allocation = Allocation.new(allocation_params)
if allocation.save
if from_group_account
from_account_id = group.status_account_id
end
m = Membership.find_by(group_id: allocation_params[:group_id], member_id: allocation_params[:user_id])
Transaction.create!({
datetime: allocation.created_at,
from_account_id: from_account_id || m.incoming_account_id,
to_account_id: m.status_account_id,
user_id: current_user.id,
amount: amount
})
if notify && (amount > 0)
UserMailer.notify_member_that_they_received_allocation(admin: current_user, member: user, group: group, amount: amount).deliver_later
end
if (allocation = AllocationService.create_allocation(allocation_params, notify, current_user))
render json: [allocation], status: 201
else
render status: 400, nothing: true
Expand Down
9 changes: 9 additions & 0 deletions app/extras/cobudget_cleanup.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class CobudgetCleanup
def self.archived_members_with_funds!
if DateTime.now.utc.hour == 7
Group.find_each do |g|
g.cleanup_archived_members_with_funds(user)
end
end
end
end
17 changes: 14 additions & 3 deletions app/mailers/user_mailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,20 @@ def notify_admins_funds_are_returned_to_group_account(admin:, bucket:, done_by:,
subject: "Funds from cancelled bucket have been returned to group account")
end

def notify_admins_archived_member_funds(admin: , group: ,memberlist: )
@memberlist = memberlist
@group = group
@group_user = group.ensure_group_user_exist()
mail(to: admin,
from: "Cobudget Updates <updates@cobudget.co>",
subject: "Funds from archived members is returned to group account")
end

def check_transactions_email
mail(to: "devops@greaterthan.finance",
from: "Cobudget Updates <updates@cobudget.co>",
subject: "DB transactions consistency check")
if Rails.configuration.respond_to?('devops_user')
mail(to: Rails.configuration.devops_user,
from: "Cobudget Updates <updates@cobudget.co>",
subject: "DB transactions consistency check")
end
end
end
63 changes: 63 additions & 0 deletions app/models/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,75 @@ def extend_trial
self.save
end

def find_archived_members_with_funds()
l = []
Membership.where(group_id: id).where.not(archived_at: nil).find_each do |membership|
if membership.raw_balance != 0
l.push({
membership_id: membership.id,
user_name: User.find(membership.member_id).name,
archived_at: membership.archived_at,
balance: membership.raw_balance
})
end
end
l
end

def transfer_balance_from_member_to_group_account(member_id, current_user)
m = Membership.find(member_id)
amount = m.raw_balance
ActiveRecord::Base.transaction do
a = Allocation.create(user_id: member_id, group_id: id, amount: -amount)
Transaction.create!({
datetime: a.created_at,
from_account_id: m.status_account_id,
to_account_id: status_account_id,
user_id: current_user.id,
amount: amount
})
end
end

def transfer_memberships_to_group_account(transfer_from_list, current_user)
group_membership = ensure_group_account_exist
transfer_from_list.each do |e|
transfer_balance_from_member_to_group_account(e[:membership_id], current_user)
end

mail_admins_about_members(transfer_from_list)
end

def for_each_admin
Membership.where(group_id: id, is_admin: :true, archived_at: nil).find_each do |admin|
yield admin
end
end

def mail_admins_about_members(memberlist)
if memberlist.length > 0
l = memberlist.map { |e|
e[:archived_at] = e[:archived_at].strftime("%B %d, %Y")
e[:balance] = Money.new(e[:balance] * 100, currency_code).format
}
for_each_admin do |admin|
UserMailer.notify_admins_archived_member_funds(admin: admin.member.name_and_email,
group: self, memberlist: memberlist).deliver_later
end
if Rails.configuration.respond_to?('devops_user')
UserMailer.notify_admins_archived_member_funds(admin: Rails.configuration.devops_user,
group: self, memberlist: memberlist).deliver_later
end
end
end

def cleanup_archived_members_with_funds(current_user)
l = find_archived_members_with_funds()
if l.length > 0
transfer_memberships_to_group_account(l, current_user)
end
end

def add_member(user)
memberships.create!(member: user, is_admin: false)
end
Expand Down
21 changes: 21 additions & 0 deletions app/services/allocation_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,27 @@ def self.check_csv_for_errors(csv:, group:)
errors if errors.any?
end

def self.create_allocation(allocation_params, notify, current_user)
allocation = Allocation.new(allocation_params)
amount = allocation_params[:amount]
if allocation.save
m = Membership.find_by(group_id: allocation_params[:group_id], member_id: allocation_params[:user_id])
Transaction.create!({
datetime: allocation.created_at,
from_account_id: m.incoming_account_id,
to_account_id: m.status_account_id,
user_id: current_user.id,
amount: amount
})
if notify && (amount > 0)
UserMailer.notify_member_that_they_received_allocation(admin: current_user, member: user, group: group, amount: amount).deliver_later
end
allocation
else
nil
end
end

def self.generate_csv_upload_preview(csv:, group:)
csv.group_by { |row| row[0].downcase }.map do |email, rows|
allocation_amount = rows.sum { |row| row[1].to_f }
Expand Down
23 changes: 23 additions & 0 deletions app/views/user_mailer/notify_admins_archived_member_funds.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<p>
Archived members with funds has been found in <%= @group.name %>
</p>

<p>
The funds has been transferred to the group account <%= @group_user.name %> which you will find in the list of funders.
</p>

<table style="width:80%;border: 1px solid black;border-spacing: 5px;">
<caption><strong>Archived members with funds</strong></caption>
<tr>
<th style="text-align: left;">User</th>
<th style="text-align: left;">Archived</th>
<th style="text-align: right;">Amount</th>
</tr>
<% @memberlist.each do |m| %>
<tr>
<td><%= m[:user_name] %></td>
<td><%= m[:archived_at] %></td>
<td style="text-align: right;"><%= m[:balance] %></td>
</tr>
<% end %>
</table>
3 changes: 3 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@
config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
config.action_mailer.default_url_options = { host: 'localhost:9000' }
config.action_mailer.raise_delivery_errors = true

# Devops user. Mails will be sent to the user when it's sent to group admins
config.devops_user = "devops@yourdomain.org"
end
3 changes: 3 additions & 0 deletions config/environments/production.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@
:password => ENV['SMTP_PASSWORD'],
:domain => ENV['SMTP_DOMAIN'],
:enable_starttls_auto => true

config.devops_user = ENV['DEVOPS_MAIL']

}

end
1 change: 1 addition & 0 deletions lib/tasks/cobudget.rake
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ namespace :cobudget do
DeliverRecentActivityEmails.to_daily_digest_subscribers!
DeliverRecentActivityEmails.to_weekly_digest_subscribers!
DeliverCheckTransactionsEmail.check_transactions!
CobudgetCleanup.archived_members_with_funds!
end
end
50 changes: 50 additions & 0 deletions spec/models/group_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'rails_helper'

RSpec.describe Group, :type => :model do
after { ActionMailer::Base.deliveries.clear }
describe "#add_admin(user)" do
context "user already member of group" do
it "makes the user an admin of group" do
Expand Down Expand Up @@ -65,4 +66,53 @@
end
end
end

describe "membership cleanup" do
context "by moving funds from archived member to group account" do
before do
admins = create_list(:user, 2)
admins.each { |a| group.add_admin(a) }
normal_users = create_list(:user, 3)
@normal_memberships = normal_users.map { |u| group.add_member(u) }
normal_users.each { |u| create(:allocation, user: u, group: group, amount: 10) }
@normal_memberships.each { |m| create(:transaction, from_account_id: m.incoming_account_id,
to_account_id: m.status_account_id, user_id: user.id, amount: 10) }
archived_users = create_list(:user, 3)
@archived_memberships = archived_users.map { |u| group.add_member(u) }
archived_users.each { |u| create(:allocation, user: u, group: group, amount: 7) }
@archived_memberships.each { |m| create(:transaction, from_account_id: m.incoming_account_id,
to_account_id: m.status_account_id, user_id: user.id, amount: 7) }
@archived_memberships.each { |m| m.archive! }
group.cleanup_archived_members_with_funds(group.ensure_group_user_exist())
@group_membership = group.ensure_group_account_exist()
end

it "has moved funds from archived users" do
@archived_memberships.each do |m|
expect(m.raw_balance).to eq(0)
expect(Account.find(m.status_account_id).balance).to eq(0)
end
end

it "has not touched funds in non-archived users" do
@normal_memberships.each do |m|
expect(m.raw_balance).to eq(10)
expect(Account.find(m.status_account_id).balance).to eq(10)
end
end

it "has moved the funds from echived users to group account" do
expect(@group_membership.raw_balance).to eq(21)
expect(Account.find(@group_membership.status_account_id).balance).to eq(21)
end

it "sends mails to admins" do
sent_emails = ActionMailer::Base.deliveries
recipients = sent_emails.map { |email| email.to.first }
admin_emails = Membership.where(group_id: group.id, is_admin: :true).map { |admin| admin.member.email }
expect(recipients).to match_array(admin_emails)
expect(sent_emails.first.body).to include("transferred")
end
end
end
end