Commit 3a4eaf58 authored by Alexandre Friquet's avatar Alexandre Friquet

Merge branch 'master' into 50-print-adherent-licence

parents 4a9e635e 47634225
......@@ -6,8 +6,10 @@
## Comment reproduire ?
## Test(s) de recette
1. Étant donné...
1. Lorsque je...
1. Alors...
/label ~anomalie
......@@ -94,6 +94,10 @@ a {
@include button-color($oligaa-green);
}
&.billed {
@include button-color($oligaa-green);
}
& .fa {
text-align: center;
width: 1em;
......
......@@ -43,3 +43,15 @@ form#search_contacts_form {
margin-right: 0;
}
}
aside#subscriptions {
ul#internal {
li {
span {
padding: 0 0.5em;
&.billed { @include button-color($oligaa-green); }
&.not-billed { @include button-color; }
}
}
}
}
......@@ -83,7 +83,7 @@ class ApplicationController < ActionController::Base
end
def novel_permitted_attributes
[ :novel_type_id, :title, :content, :public, :template, :picture,
[ :id, :novel_type_id, :title, :content, :public, :template, :picture,
activity_ids: [], attached_files_attributes: attached_file_permitted_attributes ]
end
......
......@@ -50,10 +50,11 @@ class EmailsController < ApplicationController
def create
manage_recipients_for(params[:email])
@email = Email.new(email_params)
if params[:novel_id]
@email.novel = Novel.find(params[:novel_id])
@email = Email.new
if (novel_id = params[:email][:novel_attributes][:id]).present?
@email.novel = Novel.find(novel_id)
end
@email.attributes = email_params
if @email.save
flash[:notice] = "Email créé avec succès."
redirect_to @email
......@@ -128,10 +129,9 @@ class EmailsController < ApplicationController
def email_params
permitted_params = [
:sender, :recipients_by_contact_types, :other_recipients_enabled, :other_recipients,
:member_id, :recipients
:member_id, :recipients, novel_attributes: novel_permitted_attributes
]
permitted_params << [novel_attributes: novel_permitted_attributes] unless params[:novel_id]
params.require(:email).permit(permitted_params.flatten)
params.require(:email).permit(permitted_params)
end
end
......@@ -92,8 +92,12 @@ class MembersController < ApplicationController
member = Member.includes(:contacts).where(id: params[:id]).first
if !member.nil? && member.published? || member == current_member || admin?
@member = member
@internal_subscriptions = @member.subscriptions
@external_subscriptions = Subscription.for_performances(@member.performance_ids) - @internal_subscriptions
if @member.collaborating_club?
@internal_subscriptions = @member.subscriptions
@external_subscriptions = Subscription.for_performances(@member.performance_ids) - @internal_subscriptions
elsif @member.collaborating_medicosocial_org?
@internal_subscriptions = Subscription.of_medicosocial_org(@member).by_adherent_name
end
else
authorize
end
......
......@@ -24,5 +24,10 @@ class PlatformController < ApplicationController
def index
@collaborating_clubs = Member.of_member_groups(settings.platform_collaborating_clubs).by_name
@orgs_in_db = Member.of_member_groups(settings.platform_medicosocial_orgs).by_name
@orgs_not_in_db = {}
Adherent.where.not(other_medicosocial_org: nil).group(:other_medicosocial_org).order(:other_medicosocial_org).count.each do |org_name, result|
@orgs_not_in_db[Member.new({name: org_name})] = Subscription.joins(:adherent).where(adherents: {other_medicosocial_org: org_name}).by_adherent_name.all
end
end
end
......@@ -24,11 +24,11 @@ class SubscriptionsController < ApplicationController
include AuthorizationsHelper
before_action :set_member
before_action :set_subscription, only: [:edit, :update, :destroy, :card]
before_action :authorize_member, except: [:destroy]
before_action :authorize, only: [:destroy]
before_action :set_medico_social_orgs, except: [:destroy, :card]
before_action :set_available_performances, except: [:destroy, :card]
before_action :set_subscription, only: [:edit, :update, :destroy, :card, :toggle_billing]
before_action :authorize_member, except: [:destroy, :toggle_billing]
before_action :authorize, only: [:destroy, :toggle_billing]
before_action :set_medico_social_orgs, except: [:destroy, :card, :toggle_billing]
before_action :set_available_performances, except: [:destroy, :card, :toggle_billing]
def new
@subscription = @member.subscriptions.build
......@@ -110,6 +110,11 @@ class SubscriptionsController < ApplicationController
end
end
def toggle_billing
@subscription.toggle_billing
redirect_to platform_path, notice: "L'adhésion a bien été #{@subscription.billed_at ? '' : 'dé'}facturée."
end
private
def set_member
......
......@@ -22,16 +22,20 @@
#
module AuthorizationsHelper
def can_manage_performances?(member)
admin_or_collaborator?(member)
admin_or_collaborating_club?(member)
end
def can_manage_susbscriptions?(member)
admin_or_collaborator?(member)
admin_or_collaborating_club?(member)
end
def can_see_subscriptions?(member)
admin? || (member.collaborating_medicosocial_org? && member == current_member)
end
private
def admin_or_collaborator?(member)
member.collaborator? && (admin? || member == current_member)
def admin_or_collaborating_club?(member)
admin? || (member.collaborating_club? && member == current_member)
end
end
......@@ -113,5 +113,13 @@ module LinksHelper
custom_link 'fa-id-card-o', 'Afficher carte', path, version, options
end
def custom_bill_link(path, version = :normal, options = {})
options[:class] ||= []
options[:method] = :patch
(options[:data] ||= {})[:confirm] = 'Etes-vous sûr de vouloir (dé-)facturer cet élément ?'
custom_link 'fa-eur', '€', path, version, options
end
end
......@@ -22,7 +22,7 @@
#
module SubscriptionsHelper
def internal_subscription_label(subscription)
"#{subscription.adherent.name} : #{subscription.performances_list}"
"<span class=#{subscription.billing_status} title='#{t(subscription.billing_status)}'>€</span> #{subscription.adherent.name} : #{subscription.performances_list}".html_safe
end
def external_subscription_label(subscription, member)
......
......@@ -28,7 +28,8 @@ class Email < ApplicationRecord
accepts_nested_attributes_for :novel
belongs_to :member
validates_presence_of :sender, :recipients
validates_presence_of :sender
validates_presence_of :recipients, unless: ->(email) { email.other_recipients.present? }
default_scope { order("sent_at DESC") }
scope :unsent, -> { where(sent_at: nil) }
......
......@@ -91,12 +91,24 @@ class Member < ApplicationRecord
self.update_column(:longitude, nil)
end
def collaborator?
def collaborating_club?
Settings.instance.reload.platform_collaborating_clubs.any? do |member_group|
self.member_groups.include?(member_group)
end
end
def collaborating_medicosocial_org?
Settings.instance.reload.platform_collaborating_medicosocial_orgs.any? do |member_group|
self.member_groups.include?(member_group)
end
end
def medicosocial_org?
Settings.instance.reload.platform_medicosocial_orgs.any? do |member_group|
self.member_groups.include?(member_group)
end
end
# Presenters
def admin_label
......
class Statistics::Billing::Global
def initialize(members)
@member_units = members.map { |member| Statistics::Billing::Unit.new(member) }
end
def total
@member_units.map(&:total).sum
end
def billed
@member_units.map(&:billed).sum
end
def label
@member_units.map(&:label).all? { |label| label.nil? } ? nil : "(€ : #{billed} / #{total})"
end
end
class Statistics::Billing::Unit
def initialize(member)
@member = member
end
def total
check_collaboration_or_return(0) do
@member.subscriptions.with_multiactivities_pass.length
end
end
def billed
check_collaboration_or_return(0) do
@member.subscriptions.billed.count
end
end
def label
check_collaboration_or_return(nil) do
"(€ : #{billed} / #{total})"
end
end
private
def check_collaboration_or_return(value)
return value unless @member.collaborating_club?
yield
end
end
class Statistics::Pass::Global
def initialize(members)
@member_units = members.map { |member| Statistics::Pass::Unit.new(member) }
end
def total
@member_units.map(&:total).sum
end
def multi
@member_units.map(&:multi).sum
end
def mono
total - multi
end
def label
@member_units.map(&:label).all? { |label| label.nil? } ? nil : "(#{multi} multi, #{mono} mono sur #{total})"
end
end
class Statistics::Pass::Unit
def initialize(member)
@member = member
end
def total
return_values = {
none: 0,
club: @member.subscriptions.count,
medicosocial_org: Subscription.of_medicosocial_org(@member).count
}
check_collaboration_or_return(return_values)
end
def multi
return_values = {
none: 0,
club: @member.subscriptions.with_multiactivities_pass.length,
medicosocial_org: Subscription.of_medicosocial_org(@member).with_multiactivities_pass.length
}
check_collaboration_or_return(return_values)
end
def mono
total - multi
end
def label
return_values = {
none: nil,
club: "(#{multi} multi, #{mono} mono sur #{total})",
medicosocial_org: "(#{multi} multi, #{mono} mono sur #{total})"
}
check_collaboration_or_return(return_values)
end
private
def check_collaboration_or_return(values)
if @member.collaborating_club?
values[:club]
elsif @member.medicosocial_org?
values[:medicosocial_org]
else
values[:none]
end
end
end
......@@ -9,6 +9,12 @@ class Subscription < ApplicationRecord
scope :for_performances, ->(performance_ids) { joins(:performances).where(performance_subscriptions: {performance_id: performance_ids}).distinct }
scope :by_adherent_name, -> { joins(:adherent).order('adherents.first_name','adherents.last_name') }
scope :billed, -> { where.not(billed_at: nil) }
scope :of_medicosocial_org, ->(member) { joins(:adherent).where(adherents: {medico_social_org: member}) }
def self.with_multiactivities_pass
all.reject { |sub| !sub.multipass? }
end
def performances_list
"#{performances.to_a.map(&:title_for_subscriptions_list).join(', ')}"
......@@ -24,6 +30,18 @@ class Subscription < ApplicationRecord
Season.new(self.created_at)
end
def multipass?
SubscriptionOption.new(self.adherent.medico_social_org,self.performances).send(:multipass_available?)
end
def toggle_billing
self.update_attribute(:billed_at, (billed_at.nil? ? DateTime.now.in_time_zone : nil))
end
def billing_status
billed_at ? 'billed' : 'not-billed'
end
private
def set_platform_number
......
......@@ -51,10 +51,7 @@ class SubscriptionOption
private
def org_is_collaborator?
return false if @medicosocial_org.nil?
platform_collaborating_medicosocial_org_groups = Settings.instance.reload.platform_collaborating_medicosocial_orgs.to_a
medicosocial_org_groups = @medicosocial_org.member_groups.to_a
!(platform_collaborating_medicosocial_org_groups & medicosocial_org_groups).empty?
@medicosocial_org.nil? ? false : @medicosocial_org.collaborating_medicosocial_org?
end
def several_activities?
......
......@@ -23,156 +23,12 @@
<% title @member.name %>
<% breadcrumb @member %>
<article class="card-block">
<h1><%= yield :title %></h1>
<p class="AdminCard-globalActions">
<%= custom_edit_link edit_member_path(@member) if current_member == @member || admin? %>
<%= custom_list_link members_path if admin? %>
</p>
<div id="public-stuff">
<%= content_tag :p, @member.description %>
<div id="offer">
<%= content_tag :section do %>
<h2>Public concerné</h2>
<ul>
<% @member.public_types.each do |public_type| %>
<li><%= public_type.title %> <%= "(" + public_type.description + ")" if public_type.description.present? %></li>
<% end %>
</ul>
<% end unless @member.public_types.empty? %>
<%= content_tag :section, class: 'omega' do %>
<h2>Activités proposées</h2>
<ul>
<% @member.activities.each do |activity| %>
<li>
<% if activity.poster? %>
<%= link_to "#{image_tag activity.poster.url(:thumb)} #{activity.title}".html_safe, activity_path(activity) %>
<% else %>
<%= link_to activity.title, activity_path(activity) %>
<% end -%>
</li>
<% end %>
</ul>
<%= content_tag :p, @member.other_activities unless @member.other_activities.blank? %>
<% end unless @member.activities.empty? %>
</div>
<section>
<h2>Adresse du siège</h2>
<%= simple_format @member.address %>
<h2>Site internet</h2>
<p><%= link_to @member.website, @member.website, :class => 'externe' if @member.website.present? %></p>
<h2>Autres coordonnées</h2>
<%= simple_format @member.join_us %>
</section>
<section class="omega">
<h2>Numéro d'affiliation</h2>
<p><%= @member.affiliation_number %></p>
<h2>Nos partenaires</h2>
<p><%= @member.partners %></p>
<h2>Informations complémentaires</h2>
<p><%= @member.more_info %></p>
</section>
</div>
</article>
<%= render partial: 'members/show/public_stuff' %>
<% if current_member %>
<aside class="card-block" id="private-stuff">
<h1>Informations privées. <small>Non visibles par un simple visiteur.</small></h1>
<h2>Identifiant</h2>
<p><%= @member.login %></p>
<h2>Contacts</h2>
<ul id="contacts">
<% @member.contacts.each do |contact| %>
<li>
<%= contact.full_info %>
<% unless contact.phone_numbers.empty? %>
<% contact.phone_numbers.each do |pn| %>
, <%= pn.kind + ' : ' if pn.kind.present? %><%= pn.number %>
<% end %>
<% end %>
</li>
<% end %>
</ul>
</aside>
<%- if can_manage_performances?(@member) %>
<aside class="card-block" id="performances">
<h1>Séances. <small>Non visibles par un simple visiteur.</small></h1>
<p class="AdminCard-globalActions">
<%= custom_add_link "Nouvelle séance", new_member_performance_path(@member) %>
</p>
<ul>
<% @member.performances.each do |perf| %>
<li>
<span class="no_print">
<%= custom_edit_link edit_member_performance_path(@member, perf), :short, class: %w(tight) %>
<%= custom_delete_link member_performance_path(@member, perf), :short, class: %w(tight) %>
</span>
<%= perf.full_title %>
</li>
<% end %>
</ul>
</aside>
<%- end %>
<%- if can_manage_susbscriptions?(@member) %>
<aside class="card-block" id="subscriptions">
<h1>Adhésions. <small>Non visibles par un simple visiteur.</small></h1>
<% if @member.affiliation_number.present? %>
<p class="AdminCard-globalActions">
<%= custom_add_link "Nouvelle adhésion", new_member_subscription_path(@member) %>
</p>
<h2>Nos adhérents</h2>
<ul id="internal">
<% @internal_subscriptions.each do |subscription| %>
<li>
<%= custom_show_card_link card_member_subscription_path(@member, subscription), :short, class: %w(tight), rel: 'modal:open' %>
<%- if admin? %>
<%= custom_edit_link edit_member_subscription_path(@member, subscription), :short, class: %w(tight) %>
<%= custom_delete_link member_subscription_path(@member, subscription), :short, class: %w(tight) %>
<%- end %>
<%= internal_subscription_label(subscription) %>
</li>
<% end %>
</ul>
<% else %>
<p>Merci de renseigner le numéro d'affiliation pour pouvoir utiliser cette fonctionnalité.<%= custom_edit_link edit_member_path(@member), :short, class: %w(tight) %></p>
<% end %>
<h2>Adhérents extérieurs</h2>
<ul id="external">
<% @external_subscriptions.each do |subscription| %>
<li>
<%= external_subscription_label(subscription, @member) %>
</li>
<% end %>
</ul>
</aside>
<%= render partial: 'members/show/private_stuff' %>
<%= render partial: 'members/show/performances' %>
<%= render partial: 'members/show/subscriptions' %>
<%- end %>
<% if admin? %>
<aside class="card-block" id="internal-stuff">
<h1>Informations internes. <small>Visibles par les administrateurs uniquement.</small></h1>
<h2>Date d'enregistrement</h2>
<p><%= l @member.registry_date if @member.registry_date.present? %></p>
<h2>Fait partie des groupes</h2>
<ul id="groups">
<% @member.member_groups.each do |mg| %>
<li><%= mg.title %></li>
<% end %>
</ul>
<h2>Administrateur</h2>
<p><%= @member.admin_label %></p>
<h2>Bloqué</h2>
<p><%= @member.blocked_label %></p>
<h2>Publié</h2>
<p><%= @member.published_label %></p>
<% end %>
</aside>
<% end %>
<%= render partial: 'members/show/admin_stuff' %>
<%
# OLIGAA - Stands for "Outil en Ligne d'Information et de Gestion des Activités
# des Associations" which is an online tool for associations to manage news,
# actors and activities.
# Copyright (C) 2010-2017 Comité Départemental du Sport Adapté de la Gironde (CDSA
# 33) <contact@cdsa33.org>
#
# This file is part of OLIGAA.
#
# OLIGAA is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# OLIGAA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OLIGAA. If not, see <http://www.gnu.org/licenses/>.
%>
<% if admin? %>
<aside class="card-block" id="internal-stuff">
<h1>Informations internes. <small>Visibles par les administrateurs uniquement.</small></h1>
<h2>Date d'enregistrement</h2>
<p><%= l @member.registry_date if @member.registry_date.present? %></p>
<h2>Fait partie des groupes</h2>
<ul id="groups">
<% @member.member_groups.each do |mg| %>
<li><%= mg.title %></li>
<%- end %>
</ul>
<h2>Administrateur</h2>
<p><%= @member.admin_label %></p>
<h2>Bloqué</h2>
<p><%= @member.blocked_label %></p>
<h2>Publié</h2>
<p><%= @member.published_label %></p>
</aside>
<%- end %>
<%
# OLIGAA - Stands for "Outil en Ligne d'Information et de Gestion des Activités
# des Associations" which is an online tool for associations to manage news,
# actors and activities.
# Copyright (C) 2010-2017 Comité Départemental du Sport Adapté de la Gironde (CDSA
# 33) <contact@cdsa33.org>
#
# This file is part of OLIGAA.
#
# OLIGAA is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# OLIGAA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OLIGAA. If not, see <http://www.gnu.org/licenses/>.
%>
<%- if can_manage_performances?(@member) %>
<aside class="card-block" id="performances">
<h1>Séances. <small>Non visibles par un simple visiteur.</small></h1>
<p class="AdminCard-globalActions">
<%= custom_add_link "Nouvelle séance", new_member_performance_path(@member) %>
</p>
<ul>
<% @member.performances.each do |perf| %>
<li>
<span class="no_print">
<%= custom_edit_link edit_member_performance_path(@member, perf), :short, class: %w(tight) %>
<%= custom_delete_link member_performance_path(@member, perf), :short, class: %w(tight) %>
</span>
<%= perf.full_title %>
</li>
<% end %>
</ul>
</aside>
<%- end %>
<%
# OLIGAA - Stands for "Outil en Ligne d'Information et de Gestion des Activités
# des Associations" which is an online tool for associations to manage news,
# actors and activities.
# Copyright (C) 2010-2017 Comité Départemental du Sport Adapté de la Gironde (CDSA
# 33) <contact@cdsa33.org>
#
# This file is part of OLIGAA.
#
# OLIGAA is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# OLIGAA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OLIGAA. If not, see <http://www.gnu.org/licenses/>.
%>
<aside class="card-block" id="private-stuff">
<h1>Informations privées. <small>Non visibles par un simple visiteur.</small></h1>
<h2>Identifiant</h2>
<p><%= @member.login %></p>
<h2>Contacts</h2>
<ul id="contacts">
<% @member.contacts.each do |contact| %>
<li>
<%= contact.full_info %>
<% unless contact.phone_numbers.empty? %>
<% contact.phone_numbers.each do |pn| %>
, <%= pn.kind + ' : ' if pn.kind.present? %><%= pn.number %>
<%- end %>
<%- end %>
</li>
<%- end %>
</ul>
</aside>
<%
# OLIGAA - Stands for "Outil en Ligne d'Information et de Gestion des Activités
# des Associations" which is an online tool for associations to manage news,
# actors and activities.
# Copyright (C) 2010-2017 Comité Départemental du Sport Adapté de la Gironde (CDSA
# 33) <contact@cdsa33.org>
#
# This file is part of OLIGAA.
#
# OLIGAA is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# OLIGAA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OLIGAA. If not, see <http://www.gnu.org/licenses/>.
%>
<article class="card-block">