Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
88c808b
alliance between diffents timebanks
gmartincor Apr 13, 2025
838cbbe
Bottom correction
gmartincor Apr 13, 2025
3d63279
class bottom corrected
gmartincor Apr 13, 2025
f6616c9
tests
gmartincor Apr 14, 2025
7e69876
Filter offer by organizations
gmartincor Apr 15, 2025
40b6fc4
Change name
gmartincor Apr 15, 2025
9249048
new tests offers visibility
gmartincor Apr 16, 2025
8e1e9c5
new test Offers Visibility
gmartincor Apr 16, 2025
08a2711
Correc test offers_controller_spec.rb
gmartincor Apr 17, 2025
a35ceab
Transfer time Between diferents organizations
gmartincor Apr 18, 2025
5897a3c
correct logic model and view
gmartincor Apr 18, 2025
6a0ab38
correct style
gmartincor Apr 18, 2025
4721f1c
deliver_later
gmartincor Apr 18, 2025
ad285fc
tests
gmartincor Apr 19, 2025
58333b6
Correct offers visibility
gmartincor Apr 20, 2025
a45b9ea
Correc test offers Visibility
gmartincor Apr 20, 2025
4db2fb6
Add cross-bank transfer validation to only allow transfers between al…
gmartincor Apr 20, 2025
4da8396
Update cross-bank transfer tests to include alliance creation
gmartincor Apr 20, 2025
4e02352
Change default posts visibility to only show current organization's p…
gmartincor Apr 20, 2025
d187452
Update tests to reflect new organization filtering behavior
gmartincor Apr 20, 2025
409b3e3
Fix tests for organization behavior change
gmartincor Apr 20, 2025
912c39a
refactor code
gmartincor Apr 24, 2025
8dcb5ae
fix tests
gmartincor Apr 24, 2025
de613b3
refactor code
gmartincor Apr 25, 2025
5850505
refactor code
gmartincor Apr 25, 2025
494d11d
structure.sql
gmartincor Apr 25, 2025
ce15317
interog-direct-transfer
gmartincor May 20, 2025
435f206
tests
gmartincor May 20, 2025
3b49a92
refactor code
gmartincor May 20, 2025
9d05f27
refactor code
gmartincor May 20, 2025
a5994e6
refactor code
gmartincor Jun 15, 2025
d118159
refactor
gmartincor Jun 15, 2025
ebf2015
refactor
gmartincor Jun 15, 2025
3f118db
refactor
gmartincor Jun 15, 2025
6d15d64
refactor
gmartincor Jun 15, 2025
86d64d0
delete comments
gmartincor Jul 27, 2025
e1e51d9
improve email writing
gmartincor Jul 27, 2025
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
28 changes: 28 additions & 0 deletions app/assets/javascripts/application/organizations_filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
$(function() {
$(document).on('change', '.organization-checkbox', function() {
var searchParams = new URLSearchParams(window.location.search);
var cat = searchParams.get('cat');
var q = searchParams.get('q');
var tag = searchParams.get('tag');

var form = $(this).closest('form');

if (cat) {
if (form.find('input[name="cat"]').length === 0) {
form.append('<input type="hidden" name="cat" value="' + cat + '">');
}
}

if (q) {
form.find('input[name="q"]').val(q);
}

if (tag) {
if (form.find('input[name="tag"]').length === 0) {
form.append('<input type="hidden" name="tag" value="' + tag + '">');
}
}

form.submit();
});
});
6 changes: 4 additions & 2 deletions app/controllers/offers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ def model
def show
super

member = @offer.user.members.find_by(organization: current_organization)
@destination_account = member.account if member
if @offer.user
member = @offer.user.members.find_by(organization: current_organization)
@destination_account = member.account if member
end
end
end
79 changes: 79 additions & 0 deletions app/controllers/organization_alliances_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
class OrganizationAlliancesController < ApplicationController
before_action :authenticate_user!
before_action :member_should_exist_and_be_active
before_action :authorize_admin
before_action :find_alliance, only: [:update, :destroy]

def index
@status = params[:status] || "pending"

@alliances = case @status
when "pending"
current_organization.pending_sent_alliances.includes(:source_organization, :target_organization) +
current_organization.pending_received_alliances.includes(:source_organization, :target_organization)
when "accepted"
current_organization.accepted_alliances.includes(:source_organization, :target_organization)
when "rejected"
current_organization.rejected_alliances.includes(:source_organization, :target_organization)
else
[]
end
end

def create
@alliance = OrganizationAlliance.new(
source_organization: current_organization,
target_organization_id: params[:organization_alliance][:target_organization_id],
status: "pending"
)

if @alliance.save
flash[:notice] = t("organization_alliances.created")
else
flash[:error] = @alliance.errors.full_messages.to_sentence
end

redirect_back fallback_location: organizations_path
end

def update
authorize @alliance

if @alliance.update(status: params[:status])
flash[:notice] = t("organization_alliances.updated")
else
flash[:error] = @alliance.errors.full_messages.to_sentence
end

redirect_to organization_alliances_path
end

def destroy
authorize @alliance

if @alliance.destroy
flash[:notice] = t("organization_alliances.destroyed")
else
flash[:error] = t("organization_alliances.error_destroying")
end

redirect_to organization_alliances_path
end

private

def find_alliance
@alliance = OrganizationAlliance.find(params[:id])
end

def authorize_admin
unless current_user.manages?(current_organization)
flash[:error] = t("organization_alliances.not_authorized")
redirect_to root_path
end
end

def alliance_params
params.require(:organization_alliance).permit(:target_organization_id)
end
end
58 changes: 58 additions & 0 deletions app/controllers/organization_transfers_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
class OrganizationTransfersController < ApplicationController
before_action :authenticate_user!
before_action :check_manager_role
before_action :set_organizations, only: [:new]
before_action :validate_alliance, only: [:new, :create]

def new
@transfer = Transfer.new
end

def create
@transfer = Transfer.new(transfer_params)
@transfer.source = current_organization.account
@transfer.destination = destination_organization.account
@transfer.post = nil
persister = ::Persister::TransferPersister.new(@transfer)

if persister.save
redirect_to organization_path(destination_organization),
notice: t('organizations.transfers.create.success')
else
set_organizations
flash.now[:error] = t('organizations.transfers.create.error', error: @transfer.errors.full_messages.to_sentence)
render :new
end
end

private

def transfer_params
params.require(:transfer).permit(:amount, :hours, :minutes, :reason)
end

def check_manager_role
unless current_user.manages?(current_organization)
redirect_to root_path, alert: t('organization_alliances.not_authorized')
end
end

def set_organizations
@source_organization = current_organization
@destination_organization = destination_organization
end

def destination_organization
@destination_organization ||= Organization.find(params[:destination_organization_id])
rescue ActiveRecord::RecordNotFound
redirect_to organizations_path, alert: t('application.tips.user_not_found')
end

def validate_alliance
alliance = current_organization.alliance_with(destination_organization)
unless alliance && alliance.accepted?
redirect_to organizations_path,
alert: t('transfers.cross_bank.no_alliance')
end
end
end
25 changes: 21 additions & 4 deletions app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ class PostsController < ApplicationController
def index
context = model.active.of_active_members

if current_organization.present?
context = context.where(
organization_id: current_organization.id
)
if current_user.present? && current_organization.present?
if params[:show_allied].present?
allied_org_ids = current_organization.allied_organizations.pluck(:id)
org_ids = [current_organization.id] + allied_org_ids
context = context.by_organizations(org_ids)
elsif !params[:org].present?
context = context.by_organization(current_organization.id)
end
end

posts = apply_scopes(context)
Expand Down Expand Up @@ -71,6 +75,19 @@ def destroy
redirect_to send("#{resources}_path") if post.update!(active: false)
end

def contact
@post = Post.find(params[:id])

if current_user && current_organization != @post.organization && current_user.active?(current_organization)
OrganizationNotifier.contact_request(@post, current_user, current_organization).deliver_later
flash[:notice] = t('posts.contact.success')
else
flash[:error] = t('posts.contact.error')
end

redirect_to @post
end

private

def resource
Expand Down
96 changes: 94 additions & 2 deletions app/controllers/transfers_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ class TransfersController < ApplicationController

def create
@source = find_source

if params[:cross_bank] == "true" && params[:post_id].present?
post = Post.find(params[:post_id])
create_cross_bank_transfer(post)
return
end

@account = Account.find(transfer_params[:destination])

transfer = Transfer.new(
Expand All @@ -23,16 +30,21 @@ def new
current_organization,
current_user,
params[:offer],
params[:destination_account_id]
params[:destination_account_id],
params[:cross_bank] == "true"
)

@cross_bank = params[:cross_bank] == "true"
@offer = transfer_factory.offer

render(
:new,
locals: {
accountable: transfer_factory.accountable,
transfer: transfer_factory.build_transfer,
offer: transfer_factory.offer,
sources: transfer_factory.transfer_sources
sources: transfer_factory.transfer_sources,
cross_bank: @cross_bank
}
)
end
Expand All @@ -49,6 +61,86 @@ def delete_reason

private

def create_cross_bank_transfer(post)
transfer_factory = TransferFactory.new(
current_organization,
current_user,
post.id,
nil,
true
)

destination_organization = transfer_factory.destination_organization

unless current_organization.alliance_with(destination_organization)&.accepted?
redirect_back fallback_location: post,
alert: t('transfers.cross_bank.no_alliance')
return
end

@persisters = []

user_account = current_user.members.find_by(organization: current_organization).account
org_account = current_organization.account

if user_account.id != org_account.id
user_to_org_transfer = Transfer.new(
source: user_account,
destination: org_account,
amount: transfer_params[:amount],
reason: post.description,
post: post
)
@persisters << ::Persister::TransferPersister.new(user_to_org_transfer)
end

org_to_org_transfer = Transfer.new(
source: org_account,
destination: destination_organization.account,
amount: transfer_params[:amount],
reason: post.description,
post: post
)
@persisters << ::Persister::TransferPersister.new(org_to_org_transfer)

member = post.user.members.find_by(organization: destination_organization)
if member && member.account
org_to_user_transfer = Transfer.new(
source: destination_organization.account,
destination: member.account,
amount: transfer_params[:amount],
reason: post.description,
post: post
)
@persisters << ::Persister::TransferPersister.new(org_to_user_transfer)
else
redirect_back fallback_location: post, alert: t('transfers.cross_bank.error')
return
end

if persisters_saved?
redirect_to post, notice: t('transfers.cross_bank.success')
else
@persisters.each do |persister|
persister.transfer.destroy if persister.transfer.persisted?
end
redirect_back fallback_location: post, alert: @error_messages || t('transfers.cross_bank.error')
end
end

def persisters_saved?
@error_messages = []

@persisters.each do |persister|
unless persister.save
@error_messages << persister.transfer.errors.full_messages.to_sentence
return false
end
end

true
end

def find_source
if admin?
Account.find(transfer_params[:source])
Expand Down
17 changes: 17 additions & 0 deletions app/helpers/organizations_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module OrganizationsHelper
def filterable_organizations
Organization.all.order(:name)
end

def allied_organizations
return [] unless current_organization

allied_org_ids = current_organization.accepted_alliances.map do |alliance|
alliance.source_organization_id == current_organization.id ?
alliance.target_organization_id : alliance.source_organization_id
end

organizations = Organization.where(id: allied_org_ids + [current_organization.id])
organizations.order(:name)
end
end
11 changes: 11 additions & 0 deletions app/helpers/transfers_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,15 @@ def accounts_from_movements(transfer, with_links: false)
end
end
end

def is_bank_to_bank_transfer?(transfer)
return false unless transfer

source_account = transfer.movements.find_by('amount < 0')&.account
destination_account = transfer.movements.find_by('amount > 0')&.account

source_account&.accountable_type == 'Organization' &&
destination_account&.accountable_type == 'Organization' &&
transfer.post.nil?
end
end
14 changes: 14 additions & 0 deletions app/mailers/organization_notifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,18 @@ def no_membership_warning(user)
)
end
end

def contact_request(post, requester, requester_organization)
@post = post
@requester = requester
@requester_organization = requester_organization
@offerer = post.user

I18n.with_locale(@offerer.locale) do
mail(
to: @offerer.email,
subject: t('organization_notifier.contact_request.subject', post: @post.title)
)
end
end
end
Loading