diff --git a/README.md b/README.md index f556ba1..85f54e0 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,6 @@ - info@coaching4dogs.xx (kein Admin-Account) - benny@probuddy.de - timo@tbuddy.de - - tretslag@gmail.com \ No newline at end of file + - tretslag@gmail.com +- `docker exec -it pb-php /bin/bash` +- SELECT * FROM profile WHERE JSON_CONTAINS( `teams_js`, '{"team_id":"75"}' ); \ No newline at end of file diff --git a/src/client/app/js/app/core/Dict.js b/src/client/app/js/app/core/Dict.js index b6964a5..ba385ed 100644 --- a/src/client/app/js/app/core/Dict.js +++ b/src/client/app/js/app/core/Dict.js @@ -541,7 +541,8 @@ app.core.Dict = { "APPOINTMENT_CATEGORIES_MISSING_FOR_ADMIN" : "Deinem Gruppenprofil wurden keine Kategorien zugewiesen. Bitte benachrichtige den Gruppeninhaber.", "NOTE_NO_SERIAL_APPOINTMENT_EDITING_AFTER_PUBLISHING" : "Hinweis: Serientermine können nach ihrer Veröffentlichung nur noch einzelnd bearbeitet werden.", "STATS_REPORTING" : 'Reporting', - 'STATS_PLANNING' : 'Planung' + 'STATS_PLANNING' : 'Planung', + "DO_YOU_REALLY_WANT_TO_DELETE_THIS_CONTRACT" : "Möchtest Du diesen Vertrag wirklich löschen?", }, "en" : { } diff --git a/src/client/manager/js/app/components/contract/ContractAppointmentAssignDualList.js b/src/client/manager/js/app/components/contract/ContractAppointmentAssignDualList.js index e119ee6..ef84a3a 100644 --- a/src/client/manager/js/app/components/contract/ContractAppointmentAssignDualList.js +++ b/src/client/manager/js/app/components/contract/ContractAppointmentAssignDualList.js @@ -12,6 +12,11 @@ const ContractAppointmentAssignDualList = { self.contracts = props.get( 'contracts'); self.attendedAppointments = props.get( 'attendedAppointments' ); + self.childObj = {}; + for (const prop in profile.child_profile_js) { + self.childObj[profile.child_profile_js[prop]['id']] = profile.child_profile_js[prop]['name']; + } + this.render( { profile : profile, @@ -131,6 +136,10 @@ const ContractAppointmentAssignDualList = { } aSubject += a.subject + ', ' + moment( a.start_dt ).format( 'DD.MM.YYYY' ); + if (a.attendee_child_id !== null) { + aSubject += ' (' + self.childObj[a.attendee_child_id] + ')'; + } + if ( self.selectedContractId && self.attendedAppointments[ aai ].contractId == self.selectedContractId ) { $select.append( diff --git a/src/client/manager/js/app/views/contract/ContractCharging.js b/src/client/manager/js/app/views/contract/ContractCharging.js index d3f9fd5..ef3b0d6 100644 --- a/src/client/manager/js/app/views/contract/ContractCharging.js +++ b/src/client/manager/js/app/views/contract/ContractCharging.js @@ -30,7 +30,6 @@ const ContractCharging = { break; } } - return m; } diff --git a/src/client/manager/js/app/views/contract/ContractEdit.js b/src/client/manager/js/app/views/contract/ContractEdit.js index fcf97a9..f504ea0 100644 --- a/src/client/manager/js/app/views/contract/ContractEdit.js +++ b/src/client/manager/js/app/views/contract/ContractEdit.js @@ -21,8 +21,7 @@ const ContractEdit = { self = this; self.contract = null; - - this.render( { groupId : groupId } ); + self.contractIsDeletable = false; app.rpc.call( 'Contract', @@ -32,11 +31,16 @@ const ContractEdit = { }, function( res ) { - if ( res && res.hasOwnProperty( 'data' ) && res.data.hasOwnProperty( 'contractData' ) ) + if ( res && res.hasOwnProperty( 'data' )) { - self.contract = self.createInstance( 'Contract', res.data.contractData ); + if ( res.data.hasOwnProperty( 'contractData' ) ) { + self.contract = self.createInstance( 'Contract', res.data.contractData ); + } + if ( res.data.hasOwnProperty( 'contractIsDeletable' ) ) { + self.contractIsDeletable = res.data.contractIsDeletable; + } } - + this.render( { groupId : groupId, contractIsDeletable: self.contractIsDeletable } ); const $compContractForm = self.createComponent( 'contract-form', $container.find( '[f-id="container-contract-form"]' ).first().get( 0 ), @@ -89,10 +93,69 @@ const ContractEdit = { } }); + if (self.contractIsDeletable) { + $container.find( '[data-id="btnDeleteContract"]').click( function() + { + + let $modalRoot = $container.find( '[data-id="modal-confirm-delete-contract"]' ).first(); + $modalRoot.find( '[data-id="section-confirm-delete-contract"]' ).first().show(); + $modalRoot.find( '[data-id="section-loader"]' ).first().hide(); + $modalRoot.on( 'shown.bs.modal', function() + { + $modalRoot.find( '[data-id="btnDelete"]' ).first().off( "click" ); + $modalRoot.find( '[data-id="btnDelete"]' ).first().click( function() + { + $(this).off( "click" ); + + $modalRoot.find( '[data-id="section-confirm-delete-contract"]' ).first().hide(); + $modalRoot.find( '[data-id="section-loader"]' ).first().show(); + + app.rpc.call( + 'Contract', + 'delete', + { + contractId : contractId + }, + function( resp ) + { + if ( resp && resp.hasOwnProperty( 'code' ) && resp.code == 200 ) + { + app.UI.toastSuccess( 'Vertrag wurde erfolgreich gelöscht.', 'Vertrag gelöscht' ); + if ( redirectPath ) + { + app.redirect( redirectPath ); + } + else + { + app.redirect( 'contract/list/' + groupId ); + } + } + else + { + app.UI.toastError( 'Der Vertrag konnte nicht gelöscht werden, ' + + 'da er entweder mindestens eine verknüpfte Verrechnung oder bereits ' + + 'eine Einzahlung stattgefunden hat', + 'Fehler' ); + } + $modalRoot.modal( 'hide' ); + } + ); + }); + }); + $modalRoot.on( 'hidden.bs.modal', function() + { + $modalRoot.modal( 'dispose' ); + }); + $modalRoot.modal( 'show' ); + } + ); + } + $container.find( '.sk-loading' ).toggleClass( 'sk-loading' ); }.bind ( this ) ); + }, destroy : function() diff --git a/src/client/manager/js/app/views/contract/contract-edit.html b/src/client/manager/js/app/views/contract/contract-edit.html index 175c69c..63669f3 100644 --- a/src/client/manager/js/app/views/contract/contract-edit.html +++ b/src/client/manager/js/app/views/contract/contract-edit.html @@ -40,10 +40,62 @@ href="javascript:history.back()"> Abbrechen + <% if ( true === contractIsDeletable ) { %> + + <% } %> + + + \ No newline at end of file diff --git a/src/client/manager/js/app/views/contract/contract-master-data.html b/src/client/manager/js/app/views/contract/contract-master-data.html index 9cce9fb..95dd320 100644 --- a/src/client/manager/js/app/views/contract/contract-master-data.html +++ b/src/client/manager/js/app/views/contract/contract-master-data.html @@ -118,6 +118,49 @@ +
+ +
+ +
+
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
diff --git a/src/server/server/control/TB_Server_Control_Contract.php b/src/server/server/control/TB_Server_Control_Contract.php index 5e6dece..1c6fdfc 100644 --- a/src/server/server/control/TB_Server_Control_Contract.php +++ b/src/server/server/control/TB_Server_Control_Contract.php @@ -151,7 +151,7 @@ class TB_Server_Control_Contract { $resp->addData( 'contractAppointments', [] ); } - + $resp->addData('contractIsDeletable', $contract->isDeletable()); return $resp; } @@ -515,6 +515,32 @@ class TB_Server_Control_Contract return $resp; } + public static function delete( TB_Server_Core_RequestData $params ) + { + $resp = new TB_Server_Core_Response(); + + $sessionProfile = TB_Server_Core_Session::get()->getProfile(); + $contractId = $params->get('contractId' ); + $contract = TB_Shared_Ent_TeamData_Contract::get( $contractId ); + if ( NULL === $contract ) + { + throw new \Exception( 'Contract not found.' ); + } + + if ( false === $sessionProfile->isAdminOfTeam( $contract->team_id ) && $sessionProfile->id != $contract->profile_id ) + { + throw new \Exception('Profile is not allowed to delete contract'); + } + if ( !$contract->isDeletable() ) + { + throw new \Exception('Contract is not deletable'); + } + + $contract->delete(); + + return $resp; + } + public static function updateAttendances( TB_Server_Core_RequestData $params ) { $resp = new TB_Server_Core_Response(); diff --git a/src/server/server/control/TB_Server_Control_Team.php b/src/server/server/control/TB_Server_Control_Team.php index 0103561..1f1c89c 100644 --- a/src/server/server/control/TB_Server_Control_Team.php +++ b/src/server/server/control/TB_Server_Control_Team.php @@ -912,6 +912,11 @@ class TB_Server_Control_Team { $cZipCode = $params->get( 'zip_code' ); $cCity = $params->get( 'city' ); $cCountry = $params->get( 'country' ); + $cBankCode = $params->get( 'bank_code' ); + $cAccountNumber = $params->get( 'account_number' ); + $cBankName = $params->get( 'bank_name' ); + $cPaypalMe = $params->get( 'paypal_me' ); + if ( !$cName || !$cStreet || !$cZipCode || !$cCity || !$cCountry ) { @@ -923,7 +928,11 @@ class TB_Server_Control_Team { 'street' => $cStreet, 'zip_code' => $cZipCode, 'city' => $cCity, - 'country' => $cCountry + 'country' => $cCountry, + 'bank_code' => $cBankCode, + 'account_number' => $cAccountNumber, + 'bank_name' => $cBankName, + 'paypal_me' => $cPaypalMe ); $team->save(); diff --git a/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Appointment.php b/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Appointment.php index aca5285..a552eee 100644 --- a/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Appointment.php +++ b/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Appointment.php @@ -514,7 +514,7 @@ class TB_Shared_Ent_TeamData_Appointment extends Francis_Db_Row public static function getTeamAppointmentsForAttendedProfileId( $teamId, $profileId ) { - $sql = 'SELECT a.id AS `attendee_id`, a.contract_id AS `attendee_contract_id`, app.* FROM `attendee` AS a '; + $sql = 'SELECT a.id AS `attendee_id`, a.contract_id AS `attendee_contract_id`, a.`profile_child_id` AS `attendee_child_id`, app.* FROM `attendee` AS a '; $sql .= 'LEFT JOIN appointment AS `app` ON a.appointment_id = app.id '; $sql .= 'WHERE '; $sql .= 'app.team_id = :team_id AND a.profile_id = :profile_id AND '; diff --git a/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Contract.php b/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Contract.php index f39e39d..1c82151 100644 --- a/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Contract.php +++ b/src/server/shared/ent/teamdata/TB_Shared_Ent_TeamData_Contract.php @@ -218,6 +218,12 @@ class TB_Shared_Ent_TeamData_Contract extends Francis_Db_Row TB_Shared_Ent_TeamData_Attendee::removeContractId( $this->id ); } + public function isDeletable() + { + $attendees = TB_Shared_Ent_TeamData_Attendee::getAttendancesForContractId( $this->id ); + return (int) $this->price_payed === 0 && count($attendees) === 0; + } + /** * Return table name *