]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Controllers/Crud/ContributionsController.php
Disable events from mass changes; closes #1733
[galette.git] / galette / lib / Galette / Controllers / Crud / ContributionsController.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Galette contributions controller
7 *
8 * PHP version 5
9 *
10 * Copyright © 2020-2023 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Controllers
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2020-2023 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.9.4dev - 2020-05-08
35 */
36
37 namespace Galette\Controllers\Crud;
38
39 use Galette\Features\BatchList;
40 use Analog\Analog;
41 use Galette\Controllers\CrudController;
42 use Slim\Psr7\Request;
43 use Slim\Psr7\Response;
44 use Galette\Entity\Adherent;
45 use Galette\Entity\Contribution;
46 use Galette\Entity\Transaction;
47 use Galette\Repository\Members;
48 use Galette\Entity\ContributionsTypes;
49 use Galette\Repository\PaymentTypes;
50
51 /**
52 * Galette contributions controller
53 *
54 * @category Controllers
55 * @name ContributionsController
56 * @package Galette
57 * @author Johan Cwiklinski <johan@x-tnd.be>
58 * @copyright 2020-2023 The Galette Team
59 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
60 * @link http://galette.tuxfamily.org
61 * @since Available since 0.9.4dev - 2020-05-02
62 */
63
64 class ContributionsController extends CrudController
65 {
66 use BatchList;
67
68 // CRUD - Create
69
70 /**
71 * Add/Edit page
72 *
73 * Only a few things changes in add and edit pages,
74 * boths methods will use this common one.
75 *
76 * @param Request $request PSR Request
77 * @param Response $response PSR Response
78 * @param string $type Contribution type
79 * @param Contribution $contrib Contribution instance
80 *
81 * @return Response
82 */
83 public function addEditPage(
84 Request $request,
85 Response $response,
86 string $type,
87 Contribution $contrib
88 ): Response {
89 $post = $request->getParsedBody();
90
91 // check for ajax mode
92 $ajax = false;
93 if (
94 ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest')
95 || isset($post['ajax'])
96 && $post['ajax'] == 'true'
97 ) {
98 $ajax = true;
99 }
100
101 // contribution types
102 $ct = new ContributionsTypes($this->zdb);
103 $contributions_types = $ct->getList($type === Contribution::TYPE_FEE);
104
105 // template variable declaration
106 $title = null;
107 if ($type === Contribution::TYPE_FEE) {
108 $title = _T("Membership fee");
109 } else {
110 $title = _T("Donation");
111 }
112
113 if ($contrib->id != '') {
114 $title .= ' (' . _T("modification") . ')';
115 } else {
116 $title .= ' (' . _T("creation") . ')';
117 }
118
119 $params = [
120 'page_title' => $title,
121 'required' => $contrib->getRequired(),
122 'contribution' => $contrib,
123 'adh_selected' => $contrib->member,
124 'type' => $type
125 ];
126
127 // contribution types
128 $params['type_cotis_options'] = $contributions_types;
129
130 // members
131 $m = new Members();
132 $members = $m->getDropdownMembers(
133 $this->zdb,
134 $this->login,
135 $contrib->member > 0 ? $contrib->member : null
136 );
137
138 $params['members'] = [
139 'filters' => $m->getFilters(),
140 'count' => $m->getCount()
141 ];
142
143 if (count($members)) {
144 $params['members']['list'] = $members;
145 }
146
147 $ext_membership = '';
148 if ($contrib->isFee() || $type === Contribution::TYPE_FEE) {
149 $ext_membership = $this->preferences->pref_membership_ext;
150 }
151 $params['pref_membership_ext'] = $ext_membership;
152 $params['autocomplete'] = true;
153 $params['mode'] = ($ajax ? 'ajax' : '');
154
155 // display page
156 $this->view->render(
157 $response,
158 'pages/contribution_form.html.twig',
159 $params
160 );
161 return $response;
162 }
163
164 /**
165 * Add page
166 *
167 * @param Request $request PSR Request
168 * @param Response $response PSR Response
169 * @param string|null $type Contribution type
170 *
171 * @return Response
172 */
173 public function add(Request $request, Response $response, string $type = null): Response
174 {
175 if ($this->session->contribution !== null) {
176 $contrib = $this->session->contribution;
177 $this->session->contribution = null;
178 } else {
179 $get = $request->getQueryParams();
180
181 $ct = new ContributionsTypes($this->zdb);
182 $contributions_types = $ct->getList($type === Contribution::TYPE_FEE);
183
184 $cparams = ['type' => array_keys($contributions_types)[0]];
185
186 //member id
187 if (isset($get[Adherent::PK]) && $get[Adherent::PK] > 0) {
188 $cparams['adh'] = (int)$get[Adherent::PK];
189 }
190
191 //transaction id
192 if (isset($get[Transaction::PK]) && $get[Transaction::PK] > 0) {
193 $cparams['trans'] = $get[Transaction::PK];
194 }
195
196 $contrib = new Contribution(
197 $this->zdb,
198 $this->login,
199 $cparams
200 );
201
202 if (isset($cparams['adh'])) {
203 $contrib->member = $cparams['adh'];
204 }
205
206 if (isset($get['montant_cotis']) && $get['montant_cotis'] > 0) {
207 $contrib->amount = $get['montant_cotis'];
208 }
209 }
210
211 return $this->addEditPage($request, $response, $type, $contrib);
212 }
213
214 /**
215 * Add action
216 *
217 * @param Request $request PSR Request
218 * @param Response $response PSR Response
219 * @param string|null $type Contribution type
220 *
221 * @return Response
222 */
223 public function doAdd(Request $request, Response $response, string $type = null): Response
224 {
225 return $this->store($request, $response, 'add', $type);
226 }
227
228 /**
229 * Choose contribution type to mass add contribution
230 *
231 * @param Request $request PSR Request
232 * @param Response $response PSR Response
233 *
234 * @return Response
235 */
236 public function massAddChooseType(Request $request, Response $response): Response
237 {
238 $filters = $this->session->filter_members;
239 $data = [
240 'id' => $filters->selected,
241 'redirect_uri' => $this->routeparser->urlFor('members')
242 ];
243
244 // display page
245 $this->view->render(
246 $response,
247 'modals/mass_choose_contributions_type.html.twig',
248 array(
249 'mode' => ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') ? 'ajax' : '',
250 'page_title' => str_replace(
251 '%count',
252 count($data['id']),
253 _T('Mass add contribution on %count members')
254 ),
255 'data' => $data,
256 'form_url' => $this->routeparser->urlFor('massAddContributions'),
257 'cancel_uri' => $this->routeparser->urlFor('members')
258 )
259 );
260 return $response;
261 }
262
263 /**
264 * Massive change page
265 *
266 * @param Request $request PSR Request
267 * @param Response $response PSR Response
268 *
269 * @return Response
270 */
271 public function massAddContributions(Request $request, Response $response): Response
272 {
273 $post = $request->getParsedBody();
274 $filters = $this->session->filter_members;
275 $type = $post['type'];
276
277 $ct = new ContributionsTypes($this->zdb);
278 $contributions_types = $ct->getList($type === Contribution::TYPE_FEE);
279
280 $contribution = new Contribution(
281 $this->zdb,
282 $this->login,
283 ['type' => array_keys($contributions_types)[0]]
284 );
285
286 $data = [
287 'id' => $filters->selected,
288 'redirect_uri' => $this->routeparser->urlFor('members'),
289 'type' => $type
290 ];
291
292 // display page
293 $this->view->render(
294 $response,
295 'modals/mass_add_contributions.html.twig',
296 array(
297 'mode' => ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') ? 'ajax' : '',
298 'page_title' => str_replace(
299 '%count',
300 count($data['id']),
301 _T('Mass add contribution on %count members')
302 ),
303 'form_url' => $this->routeparser->urlFor('doMassAddContributions'),
304 'cancel_uri' => $this->routeparser->urlFor('members'),
305 'data' => $data,
306 'contribution' => $contribution,
307 'type' => $type,
308 'require_mass' => true,
309 'required' => $contribution->getRequired(),
310 'type_cotis_options' => $contributions_types
311 )
312 );
313 return $response;
314 }
315
316 /**
317 * Do massive contribution add
318 *
319 * @param Request $request PSR Request
320 * @param Response $response PSR Response
321 *
322 * @return Response
323 */
324 public function doMassAddContributions(Request $request, Response $response): Response
325 {
326 $post = $request->getParsedBody();
327 $members_ids = $post['id'];
328 unset($post['id']);
329
330 $error_detected = [];
331
332 // flagging required fields for first step only
333 $disabled = [];
334 $success = 0;
335 $errors = 0;
336
337 foreach ($members_ids as $member_id) {
338 $post[Adherent::PK] = (int)$member_id;
339 $contrib = new Contribution($this->zdb, $this->login);
340 $contrib->disableEvents();
341
342 // regular fields
343 $valid = $contrib->check($post, $contrib->getRequired(), $disabled);
344 if ($valid !== true) {
345 $error_detected = array_merge($error_detected, $valid);
346 }
347
348 //all goes well, we can proceed
349 if (count($error_detected) == 0) {
350 $store = $contrib->store();
351 if ($store === true) {
352 ++$success;
353 $files_res = $contrib->handleFiles($_FILES);
354 if (is_array($files_res)) {
355 $error_detected = array_merge($error_detected, $files_res);
356 }
357 } else {
358 ++$errors;
359 }
360 }
361 }
362
363 if (count($error_detected) == 0) {
364 $redirect_url = $this->routeparser->urlFor('members');
365 } else {
366 //something went wrong.
367 //store entity in session
368 $redirect_url = $this->routeparser->urlFor('massAddContributions');
369 //report errors
370 foreach ($error_detected as $error) {
371 $this->flash->addMessage(
372 'error_detected',
373 $error
374 );
375 }
376 }
377
378 //redirect to calling action
379 return $response
380 ->withStatus(301)
381 ->withHeader('Location', $redirect_url);
382 }
383
384 // /CRUD - Create
385 // CRUD - Read
386
387 /**
388 * List page
389 *
390 * @param Request $request PSR Request
391 * @param Response $response PSR Response
392 * @param string $option One of 'page' or 'order'
393 * @param string|integer $value Value of the option
394 * @param string $type One of 'transactions' or 'contributions'
395 *
396 * @return Response
397 */
398 public function list(Request $request, Response $response, $option = null, $value = null, $type = null): Response
399 {
400 $ajax = false;
401 $get = $request->getQueryParams();
402
403 switch ($type) {
404 case 'transactions':
405 $raw_type = 'transactions';
406 break;
407 case 'contributions':
408 $raw_type = 'contributions';
409 break;
410 default:
411 Analog::log(
412 'Trying to load unknown contribution type ' . $type,
413 Analog::WARNING
414 );
415 return $response
416 ->withStatus(301)
417 ->withHeader(
418 'Location',
419 $this->routeparser->urlFor('me')
420 );
421 }
422
423 $filter_name = 'filter_' . $raw_type;
424 if (
425 ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest')
426 || isset($get['ajax'])
427 && $get['ajax'] == 'true'
428 ) {
429 $ajax = true;
430 $filter_name .= '_ajax';
431 }
432
433 if (isset($this->session->$filter_name)) {
434 $filters = $this->session->$filter_name;
435 } else {
436 $filter_class = '\\Galette\\Filters\\' . ucwords($raw_type . 'List');
437 $filters = new $filter_class();
438 }
439
440 //member id
441 if (isset($get[Adherent::PK]) && $get[Adherent::PK] > 0) {
442 $filters->filtre_cotis_adh = (int)$get[Adherent::PK];
443 }
444
445 if ($type === 'contributions') {
446 if (isset($request->getQueryParams()['max_amount'])) {
447 $filters->filtre_transactions = true;
448 $filters->max_amount = (int)$request->getQueryParams()['max_amount'];
449 }
450 }
451
452 if ($option !== null) {
453 switch ($option) {
454 case 'page':
455 $filters->current_page = (int)$value;
456 break;
457 case 'order':
458 $filters->orderby = $value;
459 break;
460 case 'member':
461 $filters->filtre_cotis_adh = ($value === 'all' ? null : $value);
462 break;
463 }
464 }
465
466 if (!$this->login->isAdmin() && !$this->login->isStaff() && $value != $this->login->id) {
467 if ($value === 'all' || empty($value)) {
468 $value = $this->login->id;
469 } else {
470 $member = new Adherent(
471 $this->zdb,
472 (int)$value,
473 [
474 'picture' => false,
475 'groups' => false,
476 'dues' => false,
477 'parent' => true
478 ]
479 );
480 if (
481 !$member->hasParent() ||
482 $member->parent->id != $this->login->id
483 ) {
484 $value = $this->login->id;
485 Analog::log(
486 'Trying to display contributions for member #' . $value .
487 ' without appropriate ACLs',
488 Analog::WARNING
489 );
490 }
491 }
492 $filters->filtre_cotis_children = $value;
493 }
494
495 $class = '\\Galette\\Entity\\' . ucwords(trim($raw_type, 's'));
496 $contrib = new $class($this->zdb, $this->login);
497
498 if (!$contrib->canShow($this->login)) {
499 Analog::log(
500 'Trying to display contributions without appropriate ACLs',
501 Analog::WARNING
502 );
503 return $response
504 ->withStatus(301)
505 ->withHeader(
506 'Location',
507 $this->routeparser->urlFor('me')
508 );
509 }
510
511 $class = '\\Galette\\Repository\\' . ucwords($raw_type);
512 $contrib = new $class($this->zdb, $this->login, $filters);
513 $contribs_list = $contrib->getList(true);
514
515 //store filters into session
516 if ($ajax === false) {
517 $this->session->$filter_name = $filters;
518 }
519
520 //assign pagination variables to the template and add pagination links
521 $filters->setSmartyPagination($this->routeparser, $this->view);
522
523 $tpl_vars = [
524 'page_title' => $raw_type === 'contributions' ?
525 _T("Contributions management") : _T("Transactions management"),
526 'contribs' => $contrib,
527 'list' => $contribs_list,
528 'nb' => $contrib->getCount(),
529 'filters' => $filters,
530 'mode' => ($ajax === true ? 'ajax' : 'std')
531 ];
532
533 if ($filters->filtre_cotis_adh != null) {
534 $member = new Adherent($this->zdb);
535 $member->enableDep('children');
536 $member->load($filters->filtre_cotis_adh);
537 $tpl_vars['member'] = $member;
538 }
539
540 if ($filters->filtre_cotis_children != false) {
541 $member = new Adherent(
542 $this->zdb,
543 $filters->filtre_cotis_children,
544 [
545 'picture' => false,
546 'groups' => false,
547 'dues' => false,
548 'parent' => true
549 ]
550 );
551 $tpl_vars['pmember'] = $member;
552 }
553
554 // hide column action in ajax mode
555 if ($ajax === true) {
556 $tpl_vars['no_action'] = true;
557 }
558
559 // display page
560 $this->view->render(
561 $response,
562 'pages/' . $raw_type . '_list.html.twig',
563 $tpl_vars
564 );
565 return $response;
566 }
567
568 /**
569 * List page for logged-in member
570 *
571 * @param Request $request PSR Request
572 * @param Response $response PSR Response
573 * @param string $type One of 'transactions' or 'contributions'
574 *
575 * @return Response
576 */
577 public function myList(Request $request, Response $response, string $type = null): Response
578 {
579 return $this->list(
580 $request->withQueryParams(
581 $request->getQueryParams() + [
582 Adherent::PK => $this->login->id
583 ]
584 ),
585 $response,
586 null,
587 null,
588 $type
589 );
590 }
591
592 /**
593 * Filtering
594 *
595 * @param Request $request PSR Request
596 * @param Response $response PSR Response
597 * @param string|null $type One of 'transactions' or 'contributions'
598 *
599 * @return Response
600 */
601 public function filter(Request $request, Response $response, string $type = null): Response
602 {
603 $ajax = false;
604 $filter_name = 'filter_' . $type;
605 if ($request->getHeaderLine('X-Requested-With') === 'XMLHttpRequest') {
606 $ajax = true;
607 $filter_name .= '_ajax';
608 }
609
610 $post = $request->getParsedBody();
611 $error_detected = [];
612
613 if ($this->session->$filter_name !== null) {
614 $filters = $this->session->$filter_name;
615 } else {
616 $filter_class = '\\Galette\\Filters\\' . ucwords($type) . 'List';
617 $filters = new $filter_class();
618 }
619
620 if (isset($post['clear_filter'])) {
621 $filters->reinit($ajax);
622 } else {
623 if (!isset($post['max_amount'])) {
624 $filters->max_amount = null;
625 }
626
627 if (
628 (isset($post['nbshow']) && is_numeric($post['nbshow']))
629 ) {
630 $filters->show = $post['nbshow'];
631 }
632
633 if (isset($post['date_field'])) {
634 $filters->date_field = $post['date_field'];
635 }
636
637 if (isset($post['end_date_filter']) || isset($post['start_date_filter'])) {
638 if (isset($post['start_date_filter'])) {
639 $filters->start_date_filter = $post['start_date_filter'];
640 }
641 if (isset($post['end_date_filter'])) {
642 $filters->end_date_filter = $post['end_date_filter'];
643 }
644 }
645
646 if (isset($post['payment_type_filter'])) {
647 $ptf = (int)$post['payment_type_filter'];
648 $ptypes = new PaymentTypes(
649 $this->zdb,
650 $this->preferences,
651 $this->login
652 );
653 $ptlist = $ptypes->getList();
654 if (isset($ptlist[$ptf])) {
655 $filters->payment_type_filter = $ptf;
656 } elseif ($ptf == -1) {
657 $filters->payment_type_filter = null;
658 } else {
659 $error_detected[] = _T("- Unknown payment type!");
660 }
661 }
662 }
663
664 $this->session->$filter_name = $filters;
665
666 if (count($error_detected) > 0) {
667 //report errors
668 foreach ($error_detected as $error) {
669 $this->flash->addMessage(
670 'error_detected',
671 $error
672 );
673 }
674 }
675
676 return $response
677 ->withStatus(301)
678 ->withHeader('Location', $this->routeparser->urlFor('contributions', ['type' => $type]));
679 }
680
681 /**
682 * Batch actions handler
683 *
684 * @param Request $request PSR Request
685 * @param Response $response PSR Response
686 * @param string $type One of 'transactions' or 'contributions'
687 *
688 * @return Response
689 */
690 public function handleBatch(Request $request, Response $response, string $type): Response
691 {
692 $filter_name = 'filter_' . $type;
693 $post = $request->getParsedBody();
694
695 if (isset($post['entries_sel'])) {
696 $filter_class = '\\Galette\\Filters\\' . ucwords($type . 'List');
697 $filters = $this->session->$filter_name ?? new $filter_class();
698 $filters->selected = $post['entries_sel'];
699 $this->session->$filter_name = $filters;
700
701 if (isset($post['csv'])) {
702 return $response
703 ->withStatus(301)
704 ->withHeader('Location', $this->routeparser->urlFor('csv-contributionslist', ['type' => $type]));
705 }
706
707 if (isset($post['delete'])) {
708 return $response
709 ->withStatus(301)
710 ->withHeader('Location', $this->routeparser->urlFor('removeContributions', ['type' => $type]));
711 }
712
713 throw new \RuntimeException('Does not know what to batch :(');
714 } else {
715 $this->flash->addMessage(
716 'error_detected',
717 _T("No contribution was selected, please check at least one.")
718 );
719
720 return $response
721 ->withStatus(301)
722 ->withHeader('Location', $this->routeparser->urlFor('contributions', ['type' => $type]));
723 }
724 }
725
726 // /CRUD - Read
727 // CRUD - Update
728
729 /**
730 * Edit page
731 *
732 * @param Request $request PSR Request
733 * @param Response $response PSR Response
734 * @param int $id Contribution id
735 * @param string|null $type Contribution type
736 *
737 * @return Response
738 */
739 public function edit(Request $request, Response $response, int $id, string $type = null): Response
740 {
741 if ($this->session->contribution !== null) {
742 $contrib = $this->session->contribution;
743 $this->session->contribution = null;
744 } else {
745 $contrib = new Contribution($this->zdb, $this->login, $id);
746 if ($contrib->id == '') {
747 //not possible to load contribution, exit
748 $this->flash->addMessage(
749 'error_detected',
750 str_replace(
751 '%id',
752 $id,
753 _T("Unable to load contribution #%id!")
754 )
755 );
756 return $response
757 ->withStatus(301)
758 ->withHeader('Location', $this->routeparser->urlFor(
759 'contributions',
760 ['type' => 'contributions']
761 ));
762 }
763 }
764
765 return $this->addEditPage($request, $response, $type, $contrib);
766 }
767
768 /**
769 * Edit action
770 *
771 * @param Request $request PSR Request
772 * @param Response $response PSR Response
773 * @param integer $id Contribution id
774 * @param string|null $type Contribution type
775 *
776 * @return Response
777 */
778 public function doEdit(Request $request, Response $response, int $id, string $type = null): Response
779 {
780 return $this->store($request, $response, 'edit', $type, $id);
781 }
782
783 /**
784 * Store contribution (new or existing)
785 *
786 * @param Request $request PSR Request
787 * @param Response $response PSR Response
788 * @param string $action Action ('edit' or 'add')
789 * @param string $type Contribution type
790 * @param integer $id Contribution id
791 *
792 * @return Response
793 */
794 public function store(Request $request, Response $response, $action, string $type, $id = null): Response
795 {
796 $post = $request->getParsedBody();
797 $url_args = [
798 'action' => $action,
799 'type' => $type
800 ];
801 if ($id !== null) {
802 $url_args['id'] = $id;
803 }
804
805 if ($action == 'edit' && isset($post['btnreload'])) {
806 $redirect_url = $this->routeparser->urlFor($action . 'Contribution', $url_args);
807 $redirect_url .= '?' . Adherent::PK . '=' . $post[Adherent::PK] . '&' .
808 ContributionsTypes::PK . '=' . $post[ContributionsTypes::PK] . '&' .
809 'montant_cotis=' . $post['montant_cotis'];
810 return $response
811 ->withStatus(301)
812 ->withHeader('Location', $redirect_url);
813 }
814
815 $error_detected = [];
816
817 if ($this->session->contribution !== null) {
818 $contrib = $this->session->contribution;
819 $this->session->contribution = null;
820 } else {
821 if ($id === null) {
822 $contrib = new Contribution($this->zdb, $this->login);
823 } else {
824 $contrib = new Contribution($this->zdb, $this->login, $id);
825 }
826 }
827
828 $disabled = [];
829
830 // regular fields
831 $valid = $contrib->check($post, $contrib->getRequired(), $disabled);
832 if ($valid !== true) {
833 $error_detected = array_merge($error_detected, $valid);
834 }
835
836 // send email to member
837 if (isset($post['mail_confirm']) && $post['mail_confirm'] == '1') {
838 $contrib->setSendmail(); //flag to send creation email
839 }
840
841 //all goes well, we can proceed
842 if (count($error_detected) == 0) {
843 $store = $contrib->store();
844 if ($store === true) {
845 $this->flash->addMessage(
846 'success_detected',
847 _T('Contribution has been successfully stored')
848 );
849 } else {
850 //something went wrong :'(
851 $error_detected[] = _T("An error occurred while storing the contribution.");
852 }
853 }
854
855 if (count($error_detected) === 0) {
856 $files_res = $contrib->handleFiles($_FILES);
857 if (is_array($files_res)) {
858 $error_detected = array_merge($error_detected, $files_res);
859 }
860 }
861
862 if (count($error_detected) == 0) {
863 $this->session->contribution = null;
864 if ($contrib->isTransactionPart() && $contrib->transaction->getMissingAmount() > 0) {
865 //new contribution
866 $redirect_url = $this->routeparser->urlFor(
867 'addContribution',
868 [
869 'type' => $post['contrib_type'] ?? $type
870 ]
871 ) . '?' . Transaction::PK . '=' . $contrib->transaction->id .
872 '&' . Adherent::PK . '=' . $contrib->member;
873 } else {
874 //contributions list for member
875 $redirect_url = $this->routeparser->urlFor(
876 'contributions',
877 [
878 'type' => 'contributions'
879 ]
880 ) . '?' . Adherent::PK . '=' . $contrib->member;
881 }
882 } else {
883 //something went wrong.
884 //store entity in session
885 $this->session->contribution = $contrib;
886 $redirect_url = $this->routeparser->urlFor($action . 'Contribution', $url_args);
887
888 //report errors
889 foreach ($error_detected as $error) {
890 $this->flash->addMessage(
891 'error_detected',
892 $error
893 );
894 }
895 }
896
897 //redirect to calling action
898 return $response
899 ->withStatus(301)
900 ->withHeader('Location', $redirect_url);
901 }
902
903 // /CRUD - Update
904 // CRUD - Delete
905
906 /**
907 * Get redirection URI
908 *
909 * @param array $args Route arguments
910 *
911 * @return string
912 */
913 public function redirectUri(array $args)
914 {
915 return $this->routeparser->urlFor('contributions', ['type' => $args['type']]);
916 }
917
918 /**
919 * Get form URI
920 *
921 * @param array $args Route arguments
922 *
923 * @return string
924 */
925 public function formUri(array $args)
926 {
927 return $this->routeparser->urlFor(
928 'doRemoveContribution',
929 $args
930 );
931 }
932
933 /**
934 * Get confirmation removal page title
935 *
936 * @param array $args Route arguments
937 *
938 * @return string
939 */
940 public function confirmRemoveTitle(array $args)
941 {
942 $raw_type = null;
943
944 switch ($args['type']) {
945 case 'transactions':
946 $raw_type = 'transactions';
947 break;
948 case 'contributions':
949 $raw_type = 'contributions';
950 break;
951 }
952
953 if (isset($args['ids'])) {
954 return sprintf(
955 _T('Remove %1$s %2$s'),
956 count($args['ids']),
957 ($raw_type === 'contributions') ? _T('contributions') : _T('transactions')
958 );
959 } else {
960 return sprintf(
961 _T('Remove %1$s #%2$s'),
962 ($raw_type === 'contributions') ? _T('contribution') : _T('transaction'),
963 $args['id']
964 );
965 }
966 }
967
968 /**
969 * Remove object
970 *
971 * @param array $args Route arguments
972 * @param array $post POST values
973 *
974 * @return boolean
975 */
976 protected function doDelete(array $args, array $post)
977 {
978 $raw_type = null;
979 switch ($args['type']) {
980 case 'transactions':
981 $raw_type = 'transactions';
982 break;
983 case 'contributions':
984 $raw_type = 'contributions';
985 break;
986 }
987
988 $class = '\\Galette\Repository\\' . ucwords($raw_type);
989 $contribs = new $class($this->zdb, $this->login);
990 $rm = $contribs->remove($args['ids'] ?? $args['id'], $this->history);
991 return $rm;
992 }
993
994 // /CRUD - Delete
995 // /CRUD
996
997 /**
998 * Get filter name in session
999 *
1000 * @param array|null $args Route arguments
1001 *
1002 * @return string
1003 */
1004 public function getFilterName(array $args = null): string
1005 {
1006 return 'filter_' . $args['type'];
1007 }
1008 }