3 * Copyright © 2003-2024 The Galette Team
5 * This file is part of Galette (https://galette.eu).
7 * Galette is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * Galette is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
21 {% extends "page.html.twig" %}
24 {% if members.list is defined %}
25 <form action="{% if transaction.id %}{{ url_for("editTransaction", {"id": transaction.id}) }}{% else %}{{ url_for("addTransaction") }}{% endif %}" enctype="multipart/form-data" method="post" class="ui form">
26 <div class="ui styled fluid accordion field">
27 <div class="active title">
28 <i class="jsonly displaynone icon dropdown" aria-hidden="true"></i>
29 {{ _T("Transaction details") }}
31 <div class="active content">
32 <div class="ui mobile reversed stackable grid">
33 <div class="{% if transaction.id %}five wide {% endif %}column">
34 <div class="field inline{% if required.trans_desc is defined and required.trans_desc == 1 %} required{% endif %}">
35 <label for="trans_desc">{{ _T("Description:") }}</label>
36 <input type="text" name="trans_desc" id="trans_desc" value="{{ transaction.description }}" maxlength="150" size="30"{% if required.trans_desc is defined and required.trans_desc == 1 %} required="required"{% endif %}/>
38 <div class="field inline{% if required.id_adh is defined and required.id_adh == 1 %} required{% endif %}">
39 <label for="id_adh" >{{ _T("Originator:") }}</label>
40 <div id="id_adh" class="jsonly search-dropdown ui input paginated"{% if required.id_adh is defined and required.id_adh == 1 %} required="required"{% endif %}>
41 <input id="id_adh_input" type="text" name="id_adh" value="{{ transaction.member is not null ? transaction.member }}" placeholder="{{ _T("Member ID") }}">
42 <i class="jsonly displaynone dropdown icon" aria-hidden="true"></i>
43 <span class="ui mini compact icon disabled button prev-results"><i class="jsonly displaynone chevron circle left icon disabled button tooltip" title="{{ _T("Load previous members...") }}" aria-hidden="true"></i></span>
44 <span class="ui mini compact icon disabled button next-results"><i class="jsonly displaynone chevron circle right icon disabled button tooltip" title="{{ _T("Load following members...") }}" aria-hidden="true"></i></span>
45 <div class="jsonly displaynone default text">{% if not transaction.member %}{{ _T("Search for name or ID and pick member") }}{% endif %}</div>
46 <div class="jsonly displaynone menu">
47 {% for k, v in members.list %}
48 <div class="item" data-value="{{ k }}">{{ v }}</div>
53 <div class="field inline{% if required.trans_date is defined and required.trans_date == 1 %} required{% endif %}">
54 <label for="trans_date">{{ _T("Date:") }}</label>
55 <div class="ui calendar" id="transaction-rangestart">
56 <div class="ui input left icon">
57 <i class="calendar icon" aria-hidden="true"></i>
58 <input type="text" class="date-pick" name="trans_date" id="trans_date" value="{{ transaction.date }}" maxlength="10"{% if required.trans_date is defined and required.trans_date == 1 %} required="required"{% endif %} placeholder="{{ _T('yyyy-mm-dd format') }}" />
62 <div class="field inline{% if required.trans_amount is defined and required.trans_amount == 1 %} required{% endif %}">
63 <label for="trans_amount">{{ _T("Amount:") }}</label>
64 <input type="text" name="trans_amount" id="trans_amount" value="{{ transaction.amount }}" maxlength="10"{% if required.trans_amount is defined and required.trans_amount == 1 %} required="required"{% endif %}/>
66 <div class="field inline{% if required.trans_payment_type is defined and required.trans_payment_type == 1 %} required{% endif %}">
68 {% set ptype = transaction.payment_type %}
69 {% include 'components/forms/payment_types.html.twig' with {
71 'varname': 'type_paiement_trans',
79 {% if transaction.id == null %}
80 <div class="field inline">
81 <label class="inline" title="{{ _T("Select a contribution type to create for dispatch transaction") }}">{{ _T("Dispatch type:") }}</label>
82 <i class="circular inverted primary small icon info tooltip" title="{{ _T("Select a contribution type to create for dispatch transaction") }}" aria-hidden="true"></i>
83 <input type="radio" name="contrib_type" id="contrib_type_fee" value="{{ constant('Galette\\Entity\\Contribution::TYPE_FEE') }}"/> <label for="contrib_type_fee">{{ _T("Membership fee") }}</label>
84 <input type="radio" name="contrib_type" id="contrib_type_donation" value="{{ constant('Galette\\Entity\\Contribution::TYPE_DONATION') }}"/> <label for="contrib_type_donation">{{ _T("Donation") }}</label>
88 {% if transaction.id %}
89 <div class="eleven wide column">
90 <div class="ui tiny header">{{ _T("Attached contributions") }}</div>
91 <table class="listing ui very compact small celled yellow table">
94 <th class="id_row">#</th>
95 <th class="left date_row">{{ _T("Date") }}</th>
96 <th class="left date_row">{{ _T("Begin") }}</th>
97 <th class="left date_row">{{ _T("End") }}</th>
98 <th class="left">{{ _T("Duration") }}</th>
99 {% if login.isAdmin() or login.isStaff() %}
100 <th class="left">{{ _T("Member") }}</th>
102 <th class="left">{{ _T("Type") }}</th>
103 <th class="left">{{ _T("Amount") }}</th>
104 {% if login.isAdmin() or login.isStaff() %}
105 <th class="actions_row">{{ _T("Actions") }}</th>
111 <th class="right bgfree" colspan="{% if login.isAdmin() or login.isStaff() %}7{% else %}5{% endif %}">{{ _T("Dispatched amount:") }}</th>
112 <th class="right bgfree">{{ transaction.getDispatchedAmount() }}</th>
116 <th class="right bgfree" colspan="{% if login.isAdmin() or login.isStaff() %}7{% else %}5{% endif %}">{{ _T("Not dispatched amount:") }}</th>
117 <th class="right bgfree">{{ transaction.getMissingAmount() }}</th>
120 {% if transaction.getMissingAmount() > 0 %}
122 <th colspan="{% if login.isAdmin() or login.isStaff() %}9{% else %}7{% endif %}">
123 <div class="ui basic fitted right aligned segment">
125 href="{{ url_for("addContribution", {"type": constant('Galette\\Entity\\Contribution::TYPE_FEE')}) }}?trans_id={{ transaction.id }}"
126 class="ui icon green compact button tooltip"
127 title="{{ _T("Create a new fee that will be attached to the current transaction") }}"
129 <i class="plus tiny icon" aria-hidden="true"></i>
130 <i class="user check icon" aria-hidden="true"></i>
131 <span class="visually-hidden">{{ _T("Create a new fee that will be attached to the current transaction") }}</span>
134 href="{{ url_for("addContribution", {"type": constant('Galette\\Entity\\Contribution::TYPE_DONATION')}) }}?trans_id={{ transaction.id }}"
135 class="ui icon green compact button tooltip"
136 title="{{ _T("Create a new donation that will be attached to the current transaction") }}"
138 <i class="plus tiny icon" aria-hidden="true"></i>
139 <i class="gift icon" aria-hidden="true"></i>
140 <span class="visually-hidden">{{ _T("Create a new donation that will be attached to the current transaction") }}</span>
144 class="ui icon blue compact button tooltip"
145 title="{{ _T("Select an existing contribution in the database, and attach it to the current transaction") }}"
148 <i class="receipt icon" aria-hidden="true"></i>
149 <span class="visually-hidden">{{ _T("Select an existing contribution in the database, and attach it to the current transaction") }}</span>
157 {% for ordre, contrib in contribs %}
158 {% set mid = contrib.member %}
159 <tr class="{{ contrib.getRowClass() }}">
163 <td class="center">{{ contrib.date }}</td>
164 <td class="center">{{ contrib.begin_date }}</td>
165 <td class="center">{{ contrib.end_date }}</td>
166 <td>{{ contrib.duration }}</td>
167 {% if login.isAdmin() or login.isStaff() %}
168 <td>{{ memberName({'id': mid}) }}</td>
170 <td>{{ contrib.type.libelle }}</td>
171 <td class="right">{{ contrib.amount }}</td>
172 {% if login.isAdmin() or login.isStaff() %}
173 <td class="actions_row">
175 href="{{ url_for("detach_contribution", {"id": transaction.id, "cid": contrib.id}) }}"
178 <i class="ui red trash icon tooltip" aria-hidden="true"></i>
179 <span class="ui special popup">{{ _T("Detach contribution from this transaction") }}</span>
185 <tr><td colspan="{% if login.isAdmin() or login.isStaff() %}9{% else %}7{% endif %}" class="emptylist">{{ _T("no contribution") }}</td></tr>
195 {% include "components/dynamic_fields.html.twig" with {'object': transaction} %}
197 <div class="ui basic center aligned segment">
198 <button type="submit" name="valid" class="ui labeled icon primary button action">
199 <i class="save icon" aria-hidden="true"></i> {{ _T("Save") }}
201 <input type="hidden" name="trans_id" value="{{ transaction.id }}"/>
202 <input type="hidden" name="valid" value="1"/>
203 {% include "components/forms/csrf.html.twig" %}
206 {% else %} {# No members #}
207 <div class="ui warning message" id="warningbox">
208 <h3>{{ _T("No member registered!") }}</h3>
210 {{ _T("Unfortunately, there is no member in your database yet,") }}
212 <a href="{{ url_for("addMember") }}">{{ _T("please create a member") }}</a>
218 {% block javascripts %}
219 <script type="text/javascript">
220 {% include "elements/js/choose_adh.js.twig" %}
221 document.getElementById('id_adh_input').type = 'hidden';
224 {% if transaction.id %}
225 {# Contributions popup #}
226 var _btnuser_mapping = function(){
227 $('#contribslist').click(function(){
229 url: '{{ url_for("contributions", {"type": "contributions"}) }}',
233 max_amount: '{{ transaction.getMissingAmount() }}'
235 {% include "elements/js/loader.js.twig" with {
236 selector: '#contribslist',
239 success: function(res){
240 _contribs_dialog(res, '{{ transaction.getMissingAmount() }}');
243 {% include "elements/js/modal.js.twig" with {
244 modal_title_twig: _T("An error occurred displaying members interface :(")|e("js"),
245 modal_without_content: true,
247 modal_deny_only: true,
248 modal_cancel_text: _T("Close")|e("js"),
249 modal_classname: "redalert",
257 var _contribs_dialog = function(res, max_amount){
258 {% include "elements/js/modal.js.twig" with {
259 modal_title_twig: _T("Contributions selection")|e("js"),
260 modal_content: "res",
261 modal_class: "contributions-selection fullscreen",
262 modal_content_class: "scrolling",
263 modal_deny_only: true,
264 modal_cancel_text: _T("Close")|e('js')
266 _contribs_ajax_mapper(res, max_amount);
269 var _contribs_ajax_mapper = function(res, max_amount){
270 $('.contributions-selection .filter.icon').remove();
271 $('.contributions-selection .infoline .button').remove();
272 $('.contributions-selection .contribution_row input[type=checkbox]').hide();
274 //Initialize Fomantic components
275 $('.contributions-selection .dropdown').dropdown();
276 {% include "elements/js/calendar.js.twig" %}
278 //Deactivate contributions list links
279 $('.contributions-selection tbody a').click(function(){
280 //for links in body (members links), we de nothing
284 //Use JS to send forms
285 $('.contributions-selection form').on('submit', function(){
288 url: _form.attr('action'),
290 data: _form.serialize(),
291 {% include "elements/js/loader.js.twig" with {
292 selector: '.contributions-selection'
294 success: function(res){
295 $('#main-container').remove();
296 $('.contributions-selection .content').append(res);
297 _contribs_ajax_mapper(res, max_amount);
300 {% include "elements/js/modal.js.twig" with {
301 modal_title_twig: _T("An error occurred displaying contributions :(")|e("js"),
302 modal_without_content: true,
304 modal_deny_only: true,
305 modal_cancel_text: _T("Close")|e("js"),
306 modal_classname: "redalert",
313 _bindDropdownsAutosubmit();
315 //Bind pagination and ordering links
316 $('.contributions-selection .pagination a, .contributions-selection thead a').click(function() {
322 max_amount: max_amount
324 {% include "elements/js/loader.js.twig" with {
325 selector: '.contributions-selection'
327 success: function(res){
328 $('#main-container').remove();
329 $('.contributions-selection .content').append(res);
330 _contribs_ajax_mapper(res, max_amount);
333 {% include "elements/js/modal.js.twig" with {
334 modal_title_twig: _T("An error occurred displaying contributions :(")|e("js"),
335 modal_without_content: true,
337 modal_deny_only: true,
338 modal_cancel_text: _T("Close")|e("js"),
339 modal_classname: "redalert",
346 //Bind reset filters button
347 $('#clear_filter').click(function(event) {
349 _this.closest('form').submit(function(event) {
352 url: _form.attr('action'),
357 {% include "elements/js/loader.js.twig" with {
358 selector: '.contributions-selection'
360 success: function(res){
361 $('#main-container').remove();
362 $('.contributions-selection .content').append(res);
363 _contribs_ajax_mapper(res, max_amount);
366 {% include "elements/js/modal.js.twig" with {
367 modal_title_twig: _T("An error occurred displaying contributions :(")|e("js"),
368 modal_without_content: true,
370 modal_deny_only: true,
371 modal_cancel_text: _T("Close")|e("js"),
372 modal_classname: "redalert",
380 $('.contributions-selection .contribution_row').click(function(){
381 $('.contributions-selection').modal('hide');
382 var _cid = $(this).find('input[name="entries_sel[]"]').val();
383 window.location.href = '{{ url_for("attach_contribution", {"id": transaction.id, "cid": "%cid"}) }}'.replace(/%cid/, _cid);
384 }).css('cursor', 'pointer').attr('title', '{{ _T("Click on a contribution row to attach it to the current transaction")|e('js') }}');