public static function process($action = 'list', $id = null, $filters = array()) { switch ($action) { case 'fulfill': $sql = "UPDATE invest_reward SET fulfilled = 1 WHERE invest = ?"; if (Model\Invest::query($sql, array($id))) { Message::Info(Text::get('admin-rewards-info-status-completed')); } else { Message::Error(Text::get('admin-rewards-error-statuschage-fail')); } throw new Redirection('/admin/rewards'); break; case 'unfill': $sql = "UPDATE invest_reward SET fulfilled = 0 WHERE invest = ?"; if (Model\Invest::query($sql, array($id))) { Message::Info(Text::get('admin-rewards-info-status-completed-pending')); } else { message::Error('Ha fallado al desmarcar'); } throw new Redirection('/admin/rewards'); break; } // edicion if ($action == 'edit' && !empty($id)) { $invest = Model\Invest::get($id); $projectData = Model\Project::get($invest->project); $userData = Model\User::getMini($invest->user); $status = Model\Project::status(); // si tratando post if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update'])) { $errors = array(); // la recompensa: $chosen = $_POST['selected_reward']; if (empty($chosen)) { // renuncia a las recompensas, bien por el/ella! $invest->rewards = array(); } else { $invest->rewards = array($chosen); } $invest->anonymous = $_POST['anonymous']; // dirección de envio para la recompensa // y datos fiscales por si fuera donativo $invest->address = (object) array('name' => $_POST['name'], 'nif' => $_POST['nif'], 'address' => $_POST['address'], 'zipcode' => $_POST['zipcode'], 'location' => $_POST['location'], 'country' => $_POST['country']); if ($invest->update($errors)) { Message::Info(Text::get('admin-rewards-info-update')); throw new Redirection('/admin/rewards'); } else { Message::Error('No se han actualizado correctamente los datos del aporte. ERROR: ' . implode(', ', $errors)); } } return new View('view/admin/index.html.php', array('folder' => 'rewards', 'file' => 'edit', 'invest' => $invest, 'project' => $projectData, 'user' => $userData, 'status' => $status)); } // listado de proyectos $projects = Model\Invest::projects(); $status = array('nok' => Text::_("Pendiente"), 'ok' => Text::_("Cumplida")); // listado de aportes if ($filters['filtered'] == 'yes') { $list = Model\Project\Reward::getChossen($filters); } else { $list = array(); } return new View('view/admin/index.html.php', array('folder' => 'rewards', 'file' => 'list', 'list' => $list, 'filters' => $filters, 'projects' => $projects, 'status' => $status)); }
if ($social_reward->icon == 'other') { $social_rewards["social_reward-{$social_reward->id}"]['children']["social_reward-{$social_reward->id}-other-orig"] = array('type' => 'html', 'title' => Text::get('rewards-field-social_reward-other'), 'html' => $original->other); $social_rewards["social_reward-{$social_reward->id}"]['children']["social_reward-{$social_reward->id}-other"] = array('title' => '', 'type' => 'textbox', 'size' => 100, 'class' => 'inline other', 'value' => $social_reward->other, 'errors' => array(), 'ok' => array(), 'hint' => Text::get('tooltip-project-social_reward-icon-other')); } // el boton al final $social_rewards["social_reward-{$social_reward->id}"]['children']["social_reward-{$social_reward->id}-buttons"] = array('type' => 'group', 'class' => 'buttons', 'children' => array("social_reward-{$social_reward->id}-ok" => array('type' => 'submit', 'label' => Text::get('form-accept-button'), 'class' => 'inline ok'))); } else { $social_rewards["social_reward-{$social_reward->id}"] = array('class' => 'reward social_reward', 'view' => 'view/dashboard/translates/rewards/reward.html.php', 'data' => array('reward' => $social_reward, 'licenses' => $this['licenses'])); } } } if (!empty($project->individual_rewards)) { foreach ($project->individual_rewards as $individual_reward) { // a ver si es el que estamos editando o no if (!empty($this["individual_reward-{$individual_reward->id}-edit"])) { $original = \Goteo\Model\Project\Reward::get($individual_reward->id); // a este grupo le ponemos estilo de edicion $individual_rewards["individual_reward-{$individual_reward->id}"] = array('type' => 'group', 'class' => 'reward individual_reward editindividual_reward', 'children' => array("individual_reward-{$individual_reward->id}-reward-orig" => array('title' => Text::get('rewards-field-individual_reward-reward'), 'type' => 'html', 'html' => $original->reward), "individual_reward-{$individual_reward->id}-reward" => array('title' => '', 'type' => 'textbox', 'size' => 100, 'class' => 'inline', 'value' => $individual_reward->reward, 'errors' => array(), 'ok' => array(), 'hint' => Text::get('tooltip-project-individual_reward-reward')), "individual_reward-{$individual_reward->id}-description-orig" => array('type' => 'html', 'title' => Text::get('rewards-field-individual_reward-description'), 'html' => $original->description), "individual_reward-{$individual_reward->id}-description" => array('type' => 'textarea', 'title' => '', 'cols' => 100, 'rows' => 4, 'class' => 'inline reward-description', 'value' => $individual_reward->description, 'errors' => array(), 'ok' => array(), 'hint' => Text::get('tooltip-project-individual_reward-description')))); // añadir el campo otros if ($individual_reward->icon == 'other') { $individual_rewards["individual_reward-{$individual_reward->id}"]['children']["individual_reward-{$individual_reward->id}-other-orig"] = array('type' => 'html', 'title' => Text::get('rewards-field-individual_reward-other'), 'html' => $original->other); $individual_rewards["individual_reward-{$individual_reward->id}"]['children']["individual_reward-{$individual_reward->id}-other"] = array('title' => '', 'type' => 'textbox', 'size' => 100, 'class' => 'inline', 'value' => $individual_reward->other, 'errors' => array(), 'ok' => array(), 'hint' => Text::get('tooltip-project-individual_reward-icon-other')); } // el boton al final $individual_rewards["individual_reward-{$individual_reward->id}"]['children']["individual_reward-{$individual_reward->id}-buttons"] = array('type' => 'group', 'class' => 'buttons', 'children' => array("individual_reward-{$individual_reward->id}-ok" => array('type' => 'submit', 'label' => Text::get('form-accept-button'), 'class' => 'inline ok'))); } else { $individual_rewards["individual_reward-{$individual_reward->id}"] = array('class' => 'reward individual_reward', 'view' => 'view/dashboard/translates/rewards/reward.html.php', 'data' => array('reward' => $individual_reward)); } } } $sfid = 'sf-project-rewards';
* Goteo 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. * * Goteo 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 Goteo. If not, see <http://www.gnu.org/licenses/agpl.txt>. * */ use Goteo\Core\View, Goteo\Library\Text, Goteo\Model\Project\Reward, Goteo\Model\Invest; $icons = Reward::icons('individual'); $project = $this['project']; $rewards = $this['rewards']; // recompensas ordenadas por importe uasort($rewards, function ($a, $b) { if ($a->amount == $b->amount) { return 0; } return $a->amount > $b->amount ? 1 : -1; }); $invests = $this['invests']; $filter = $this['filter']; // al ir mostrando, quitamos los que no cumplan // pending = solo los que tienen alguna recompensa pendientes // fulfilled = solo los que tienen todas las recompensas cumplidas // resign = solo los que hicieron renuncia a recompensa
public static function process($action = 'list', $id = null, $filters = array()) { $errors = array(); // reubicando aporte, if ($action == 'move') { // el aporte original $original = Model\Invest::get($id); $userData = Model\User::getMini($original->user); $projectData = Model\Project::getMini($original->project); //el original tiene que ser de tpv o cash y estar como 'cargo ejecutado' if ($original->method == 'paypal' || $original->status != 1) { Message::Error('No se puede reubicar este aporte!'); throw new Redirection('/admin/accounts'); } // generar aporte manual y caducar el original if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['move'])) { // si falta proyecto, error $projectNew = $_POST['project']; // @TODO a saber si le toca dinero de alguna convocatoria $campaign = null; $invest = new Model\Invest(array('amount' => $original->amount, 'user' => $original->user, 'project' => $projectNew, 'account' => $userData->email, 'method' => 'cash', 'status' => '1', 'invested' => date('Y-m-d'), 'charged' => $original->charged, 'anonymous' => $original->anonymous, 'resign' => $original->resign, 'admin' => $_SESSION['user']->id, 'campaign' => $campaign)); //@TODO si el proyecto seleccionado if ($invest->save($errors)) { //recompensas que le tocan (si no era resign) if (!$original->resign) { // sacar recompensas $rewards = Model\Project\Reward::getAll($projectNew, 'individual'); foreach ($rewards as $rewId => $rewData) { $invest->setReward($rewId); //asignar } } // cambio estado del aporte original a 'Reubicado' (no aparece en cofinanciadores) // si tuviera que aparecer lo marcaríamos como caducado if ($original->setStatus('5')) { // Evento Feed $log = new Feed(); $log->setTarget($projectData->id); $log->populate('Aporte reubicado', '/admin/accounts', \vsprintf("%s ha aportado %s al proyecto %s en nombre de %s", array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('money', $_POST['amount'] . ' €'), Feed::item('project', $projectData->name, $projectData->id), Feed::item('user', $userData->name, $userData->id)))); $log->doAdmin('money'); unset($log); Message::Info('Aporte reubicado correctamente'); throw new Redirection('/admin/accounts'); } else { $errors[] = 'A fallado al cambiar el estado del aporte original (' . $original->id . ')'; } } else { $errors[] = 'Ha fallado algo al reubicar el aporte'; } } $viewData = array('folder' => 'accounts', 'file' => 'move', 'original' => $original, 'user' => $userData, 'project' => $projectData); return new View('view/admin/index.html.php', $viewData); // fin de la historia dereubicar } // cambiando estado del aporte aporte, if ($action == 'update') { // el aporte original $invest = Model\Invest::get($id); if (!$invest instanceof Model\Invest) { Message::Error('No tenemos registro del aporte ' . $id); throw new Redirection('/admin/accounts'); } $status = Model\Invest::status(); $new = isset($_POST['status']) ? $_POST['status'] : null; if ($invest->issue && $_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update']) && $_POST['resolve'] == 1) { Model\Invest::unsetIssue($id); Model\Invest::setDetail($id, 'issue-solved', 'La incidencia se ha dado por resuelta por el usuario ' . $_SESSION['user']->name); Message::Info('La incidencia se ha dado por resuelta'); } if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['update']) && isset($new) && isset($status[$new])) { if ($new != $invest->status) { if (Model\Invest::query("UPDATE invest SET status=:status WHERE id=:id", array(':id' => $id, ':status' => $new))) { Model\Invest::setDetail($id, 'status-change' . rand(0, 9999), 'El admin ' . $_SESSION['user']->name . ' ha cambiado el estado del apote a ' . $status[$new]); Message::Info('Se ha actualizado el estado del aporte'); } else { Message::Error('Ha fallado al actualizar el estado del aporte'); } } else { Message::Error('No se ha cambiado el estado'); } throw new Redirection('/admin/accounts/details/' . $id); } return new View('view/admin/index.html.php', array('folder' => 'accounts', 'file' => 'update', 'invest' => $invest, 'status' => $status)); // fin de la historia actualizar estado } // resolviendo incidencias if ($action == 'solve') { // el aporte original $invest = Model\Invest::get($id); if (!$invest instanceof Model\Invest) { Message::Error('No tenemos registro del aporte ' . $id); throw new Redirection('/admin/accounts'); } $projectData = Model\Project::getMini($invest->project); $errors = array(); // primero cancelar switch ($invest->method) { case 'paypal': $err = array(); if (Paypal::cancelPreapproval($invest, $err)) { $errors[] = 'Preaproval paypal cancelado.'; $log_text = "El admin %s ha cancelado aporte y preapproval de %s de %s mediante PayPal (id: %s) al proyecto %s del dia %s"; } else { $txt_errors = implode('; ', $err); $errors[] = 'Fallo al cancelar el preapproval en paypal: ' . $txt_errors; $log_text = "El admin %s ha fallado al cancelar el aporte de %s de %s mediante PayPal (id: %s) al proyecto %s del dia %s. <br />Se han dado los siguientes errores: {$txt_errors}"; if ($invest->cancel()) { $errors[] = 'Aporte cancelado'; } else { $errors[] = 'Fallo al cancelar el aporte'; } } break; case 'tpv': $err = array(); if (Tpv::cancelPreapproval($invest, $err)) { $txt_errors = implode('; ', $err); $errors[] = 'Aporte cancelado correctamente. ' . $txt_errors; $log_text = "El admin %s ha anulado el cargo tpv de %s de %s mediante TPV (id: %s) al proyecto %s del dia %s"; } else { $txt_errors = implode('; ', $err); $errors[] = 'Fallo en la operación. ' . $txt_errors; $log_text = "El admin %s ha fallado al solicitar la cancelación del cargo tpv de %s de %s mediante TPV (id: %s) al proyecto %s del dia %s. <br />Se han dado los siguientes errores: {$txt_errors}"; } break; case 'cash': if ($invest->cancel()) { $log_text = "El admin %s ha cancelado aporte manual de %s de %s (id: %s) al proyecto %s del dia %s"; $errors[] = 'Aporte cancelado'; } else { $log_text = "El admin %s ha fallado al cancelar el aporte manual de %s de %s (id: %s) al proyecto %s del dia %s. "; $errors[] = 'Fallo al cancelar el aporte'; } break; } // Evento Feed $log = new Feed(); $log->setTarget($projectData->id); $log->populate('Cargo cancelado manualmente (admin)', '/admin/accounts', \vsprintf($log_text, array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('user', $userData->name, $userData->id), Feed::item('money', $invest->amount . ' €'), Feed::item('system', $invest->id), Feed::item('project', $projectData->name, $projectData->id), Feed::item('system', date('d/m/Y', strtotime($invest->invested)))))); $log->doAdmin(); unset($log); // luego resolver if ($invest->solve($errors)) { // Evento Feed $log = new Feed(); $log->setTarget($projectData->id); $log->populate('Incidencia resuelta (admin)', '/admin/accounts', \vsprintf("El admin %s ha dado por resuelta la incidencia con el botón \"Nos han hecho la transferencia\" para el aporte %s", array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('system', $id, 'accounts/details/' . $id)))); $log->doAdmin('admin'); unset($log); Message::Info('La incidencia se ha dado por resuelta, el aporte se ha pasado a manual y cobrado'); throw new Redirection('/admin/accounts'); } else { // Evento Feed $log = new Feed(); $log->setTarget($projectData->id); $log->populate('Fallo al resolver incidencia (admin)', '/admin/accounts', \vsprintf("Al admin %s le ha fallado el botón \"Nos han hecho la transferencia\" para el aporte %s", array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('system', $id, 'accounts/details/' . $id)))); $log->doAdmin('admin'); unset($log); Message::Error('Ha fallado al resolver la incidencia: ' . implode(',', $errors)); throw new Redirection('/admin/accounts/details/' . $id); } } // aportes manuales, cargamos la lista completa de usuarios, proyectos y campañas if ($action == 'add') { // listado de proyectos en campaña $projects = Model\Project::active(false, true); // usuarios $users = Model\User::getAllMini(); // campañas //@CALLSYS $calls = array(); // generar aporte manual if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['add'])) { $userData = Model\User::getMini($_POST['user']); $projectData = Model\Project::getMini($_POST['project']); $invest = new Model\Invest(array('amount' => $_POST['amount'], 'user' => $userData->id, 'project' => $projectData->id, 'account' => $userData->email, 'method' => 'cash', 'status' => '1', 'invested' => date('Y-m-d'), 'charged' => date('Y-m-d'), 'anonymous' => $_POST['anonymous'], 'resign' => 1, 'admin' => $_SESSION['user']->id)); //@CALLSYS if ($invest->save($errors)) { // Evento Feed $log = new Feed(); $log->setTarget($projectData->id); $log->populate('Aporte manual (admin)', '/admin/accounts', \vsprintf("%s ha aportado %s al proyecto %s en nombre de %s", array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('money', $_POST['amount'] . ' €'), Feed::item('project', $projectData->name, $projectData->id), Feed::item('user', $userData->name, $userData->id)))); $log->doAdmin('money'); unset($log); Model\Invest::setDetail($invest->id, 'admin-created', 'Este aporte ha sido creado manualmente por el admin ' . $_SESSION['user']->name); Message::Info('Aporte manual creado correctamente, seleccionar recompensa y dirección de entrega.'); throw new Redirection('/admin/rewards/edit/' . $invest->id); } else { $errors[] = 'Ha fallado algo al crear el aporte manual'; } } $viewData = array('folder' => 'accounts', 'file' => 'add', 'autocomplete' => true, 'users' => $users, 'projects' => $projects, 'calls' => $calls); return new View('view/admin/index.html.php', $viewData); // fin de la historia } // Informe de la financiación de un proyecto if ($action == 'report') { // estados de aporte $project = Model\Project::get($id); if (!$project instanceof Model\Project) { Message::Error('Instancia de proyecto no valida'); throw new Redirection('/admin/accounts'); } $invests = Model\Invest::getAll($id); $project->investors = Model\Invest::investors($id, false, true); $users = $project->agregateInvestors(); $investStatus = Model\Invest::status(); // Datos para el informe de transacciones correctas $Data = Model\Invest::getReportData($project->id, $project->status, $project->round, $project->passed); return new View('view/admin/index.html.php', array('folder' => 'accounts', 'file' => 'report', 'invests' => $invests, 'project' => $project, 'status' => $status, 'users' => $users, 'investStatus' => $investStatus, 'Data' => $Data)); } // cancelar aporte antes de ejecución, solo aportes no cargados if ($action == 'cancel') { $invest = Model\Invest::get($id); if (!$invest instanceof Model\Invest) { Message::Error('No tenemos objeto para el aporte ' . $id); throw new Redirection('/admin/accounts'); } $project = Model\Project::get($invest->project); $userData = Model\User::get($invest->user); if ($project->status > 3 && $project->status < 6) { $errors[] = 'No debería poderse cancelar un aporte cuando el proyecto ya está financiado. Si es imprescindible, hacerlo desde el panel de paypal o tpv'; break; } switch ($invest->method) { case 'paypal': $err = array(); if (Paypal::cancelPreapproval($invest, $err)) { $errors[] = 'Preaproval paypal cancelado.'; $log_text = "El admin %s ha cancelado aporte y preapproval de %s de %s mediante PayPal (id: %s) al proyecto %s del dia %s"; } else { $txt_errors = implode('; ', $err); $errors[] = 'Fallo al cancelar el preapproval en paypal: ' . $txt_errors; $log_text = "El admin %s ha fallado al cancelar el aporte de %s de %s mediante PayPal (id: %s) al proyecto %s del dia %s. <br />Se han dado los siguientes errores: {$txt_errors}"; if ($invest->cancel()) { $errors[] = 'Aporte cancelado'; } else { $errors[] = 'Fallo al cancelar el aporte'; } } break; case 'tpv': $err = array(); if (Tpv::cancelPreapproval($invest, $err)) { $txt_errors = implode('; ', $err); $errors[] = 'Aporte cancelado correctamente. ' . $txt_errors; $log_text = "El admin %s ha anulado el cargo tpv de %s de %s mediante TPV (id: %s) al proyecto %s del dia %s"; } else { $txt_errors = implode('; ', $err); $errors[] = 'Fallo en la operación. ' . $txt_errors; $log_text = "El admin %s ha fallado al solicitar la cancelación del cargo tpv de %s de %s mediante TPV (id: %s) al proyecto %s del dia %s. <br />Se han dado los siguientes errores: {$txt_errors}"; } break; case 'cash': if ($invest->cancel()) { $log_text = "El admin %s ha cancelado aporte manual de %s de %s (id: %s) al proyecto %s del dia %s"; $errors[] = 'Aporte cancelado'; } else { $log_text = "El admin %s ha fallado al cancelar el aporte manual de %s de %s (id: %s) al proyecto %s del dia %s. "; $errors[] = 'Fallo al cancelar el aporte'; } break; } // Evento Feed $log = new Feed(); $log->setTarget($project->id); $log->populate('Cargo cancelado manualmente (admin)', '/admin/accounts', \vsprintf($log_text, array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('user', $userData->name, $userData->id), Feed::item('money', $invest->amount . ' €'), Feed::item('system', $invest->id), Feed::item('project', $project->name, $project->id), Feed::item('system', date('d/m/Y', strtotime($invest->invested)))))); $log->doAdmin(); Model\Invest::setDetail($invest->id, 'manually-canceled', $log->html); unset($log); } // ejecutar cargo ahora!!, solo aportes no ejecutados // si esta pendiente, ejecutar el cargo ahora (como si fuera final de ronda), deja pendiente el pago secundario if ($action == 'execute' && $invest->status == 0) { $invest = Model\Invest::get($id); if (!$invest instanceof Model\Invest) { Message::Error('No tenemos objeto para el aporte ' . $id); throw new Redirection('/admin/accounts'); } $project = Model\Project::get($invest->project); $userData = Model\User::get($invest->user); switch ($invest->method) { case 'paypal': // a ver si tiene cuenta paypal $projectAccount = Model\Project\Account::get($invest->project); if (empty($projectAccount->paypal)) { // Erroraco! $errors[] = 'El proyecto no tiene cuenta paypal!!, ponersela en la seccion Contrato del dashboard del autor'; $log_text = null; // Evento Feed $log = new Feed(); $log->setTarget($project->id); $log->populate('proyecto sin cuenta paypal (admin)', '/admin/projects', \vsprintf('El proyecto %s aun no ha puesto su %s !!!', array(Feed::item('project', $project->name, $project->id), Feed::item('relevant', 'cuenta PayPal')))); $log->doAdmin('project'); unset($log); break; } $invest->account = $projectAccount->paypal; if (Paypal::pay($invest, $errors)) { $errors[] = 'Cargo paypal correcto'; $log_text = "El admin %s ha ejecutado el cargo a %s por su aporte de %s mediante PayPal (id: %s) al proyecto %s del dia %s"; $invest->status = 1; // si era incidencia la desmarcamos if ($invest->issue) { Model\Invest::unsetIssue($invest->id); Model\Invest::setDetail($invest->id, 'issue-solved', 'La incidencia se ha dado por resuelta al ejecutar el aporte manualmente por el admin ' . $_SESSION['user']->name); } } else { $txt_errors = implode('; ', $errors); $errors[] = 'Fallo al ejecutar cargo paypal: ' . $txt_errors . '<strong>POSIBLE INCIDENCIA NO COMUNICADA Y APORTE NO CANCELADO, HAY QUE TRATARLA MANUALMENTE</strong>'; $log_text = "El admin %s ha fallado al ejecutar el cargo a %s por su aporte de %s mediante PayPal (id: %s) al proyecto %s del dia %s. <br />Se han dado los siguientes errores: {$txt_errors}"; } break; case 'tpv': if (Tpv::pay($invest, $errors)) { $errors[] = 'Cargo sermepa correcto'; $log_text = "El admin %s ha ejecutado el cargo a %s por su aporte de %s mediante TPV (id: %s) al proyecto %s del dia %s"; $invest->status = 1; } else { $txt_errors = implode('; ', $errors); $errors[] = 'Fallo al ejecutar cargo sermepa: ' . $txt_errors; $log_text = "El admin %s ha fallado al ejecutar el cargo a %s por su aporte de %s mediante TPV (id: %s) al proyecto %s del dia %s <br />Se han dado los siguientes errores: {$txt_errors}"; } break; case 'cash': $invest->setStatus('1'); $errors[] = 'Aporte al contado, nada que ejecutar.'; $log_text = "El admin %s ha dado por ejecutado el aporte manual a nombre de %s por la cantidad de %s (id: %s) al proyecto %s del dia %s"; $invest->status = 1; break; } if (!empty($log_text)) { // Evento Feed $log = new Feed(); $log->setTarget($project->id); $log->populate('Cargo ejecutado manualmente (admin)', '/admin/accounts', \vsprintf($log_text, array(Feed::item('user', $_SESSION['user']->name, $_SESSION['user']->id), Feed::item('user', $userData->name, $userData->id), Feed::item('money', $invest->amount . ' €'), Feed::item('system', $invest->id), Feed::item('project', $project->name, $project->id), Feed::item('system', date('d/m/Y', strtotime($invest->invested)))))); $log->doAdmin(); Model\Invest::setDetail($invest->id, 'manually-executed', $log->html); unset($log); } } // visor de logs if ($action == 'viewer') { return new View('view/admin/index.html.php', array('folder' => 'accounts', 'file' => 'viewer')); } if ($action == 'resign' && !empty($id) && $_GET['token'] == md5('resign')) { if ($invest->setResign(true)) { Model\Invest::setDetail($invest->id, 'manually-resigned', 'Se ha marcado como donativo independientemente de las recompensas'); throw new Redirection('/admin/accounts/detail/' . $invest->id); } else { $errors[] = 'Ha fallado al marcar donativo'; } } if (!empty($errors)) { Message::Error(implode('<br />', $errors)); } // tipos de aporte $methods = Model\Invest::methods(); // estados del proyecto $status = Model\Project::status(); $procStatus = Model\Project::procStatus(); // estados de aporte $investStatus = Model\Invest::status(); // listado de proyectos $projects = Model\Invest::projects(); // usuarios cofinanciadores $users = Model\Invest::users(true); // campañas que tienen aportes $calls = Model\Invest::calls(); // extras $types = array('donative' => 'Solo los donativos', 'anonymous' => 'Solo los anónimos', 'manual' => 'Solo los manuales', 'campaign' => 'Solo con riego'); // filtros de revisión de proyecto $review = array('collect' => 'Recaudado', 'paypal' => 'Rev. PayPal', 'tpv' => 'Rev. TPV', 'online' => 'Pagos Online'); $issue = array('show' => 'Solamente las incidencias', 'hide' => 'Ocultar las incidencias'); /// detalles de una transaccion if ($action == 'details') { $invest = Model\Invest::get($id); $project = Model\Project::get($invest->project); $userData = Model\User::get($invest->user); return new View('view/admin/index.html.php', array('folder' => 'accounts', 'file' => 'details', 'invest' => $invest, 'project' => $project, 'user' => $userData, 'details' => $details, 'status' => $status, 'investStatus' => $investStatus)); } // listado de aportes if ($filters['filtered'] == 'yes') { $list = Model\Invest::getList($filters, null, 999); } else { $list = array(); } $viewData = array('folder' => 'accounts', 'file' => 'list', 'list' => $list, 'filters' => $filters, 'users' => $users, 'projects' => $projects, 'calls' => $calls, 'review' => $review, 'methods' => $methods, 'types' => $types, 'status' => $status, 'procStatus' => $procStatus, 'issue' => $issue, 'investStatus' => $investStatus); return new View('view/admin/index.html.php', $viewData); }
private function process_rewards(&$project, &$errors) { if (!isset($_POST['process_rewards'])) { return false; } $types = Model\Project\Reward::icons(''); //tratar retornos sociales foreach ($project->social_rewards as $k => $reward) { if (!empty($_POST["social_reward-{$reward->id}-remove"])) { unset($project->social_rewards[$k]); continue; } if (isset($_POST['social_reward-' . $reward->id . '-reward'])) { $reward->reward = $_POST['social_reward-' . $reward->id . '-reward']; $reward->description = $_POST['social_reward-' . $reward->id . '-description']; $reward->icon = $_POST['social_reward-' . $reward->id . '-icon']; if ($reward->icon == 'other') { $reward->other = $_POST['social_reward-' . $reward->id . '-other']; } $reward->license = $_POST['social_reward-' . $reward->id . '-' . $reward->icon . '-license']; $reward->icon_name = $types[$reward->icon]->name; } } // retornos individuales foreach ($project->individual_rewards as $k => $reward) { if (!empty($_POST["individual_reward-{$reward->id}-remove"])) { unset($project->individual_rewards[$k]); continue; } if (isset($_POST['individual_reward-' . $reward->id . '-reward'])) { $reward->reward = $_POST['individual_reward-' . $reward->id . '-reward']; $reward->description = $_POST['individual_reward-' . $reward->id . '-description']; $reward->icon = $_POST['individual_reward-' . $reward->id . '-icon']; if ($reward->icon == 'other') { $reward->other = $_POST['individual_reward-' . $reward->id . '-other']; } $reward->amount = $_POST['individual_reward-' . $reward->id . '-amount']; $reward->units = $_POST['individual_reward-' . $reward->id . '-units']; $reward->icon_name = $types[$reward->icon]->name; } } // tratar nuevos retornos if (!empty($_POST['social_reward-add'])) { $project->social_rewards[] = new Model\Project\Reward(array('type' => 'social', 'project' => $project->id, 'reward' => 'Nuevo retorno colectivo', 'icon' => '', 'license' => '')); } if (!empty($_POST['individual_reward-add'])) { $project->individual_rewards[] = new Model\Project\Reward(array('type' => 'individual', 'project' => $project->id, 'reward' => 'Nueva recompensa individual', 'icon' => '', 'amount' => '', 'units' => '')); } return true; }
public static function Projects($debug = false) { // proyectos a notificar $projects = Model\Project::review(); // para cada uno, foreach ($projects as $project) { // por ahora solo tratamos los de primera ronda y hasta 2 meses tras la financiación if ($project->days > 40 || $project->days > 360) { continue; } if ($debug) { echo "Proyecto {$project->name}, Impulsor: {$project->user->name}, email: {$project->user->email}, estado {$project->status}, lleva {$project->days} dias<br />"; } // primero los que no se bloquean // Recuerdo al autor proyecto, 2 meses despues de campaña finalizada if ($project->days == 140) { // si quedan recompensas/retornos pendientes por cumplir if (!Model\Project\Reward::areFulfilled($project->id) || !Model\Project\Reward::areFulfilled($project->id, 'social')) { if ($debug) { echo "Recompensas/Retornos pendientes<br />"; } Send::toOwner('2m_after', $project); } else { if ($debug) { echo "Recompensas/Retornos cumplidas, no se envía<br />"; } } } // Recuerdo al autor proyecto, 8 meses despues de campaña finalizada if ($project->days == 320) { // si quedan retornos pendientes por cumplir if (!Model\Project\Reward::areFulfilled($project->id, 'social')) { if ($debug) { echo "Retornos pendientes<br />"; } Send::toOwner('8m_after', $project); } else { if ($debug) { echo "Retornos cumplidos, no se envía<br />"; } } } // ahora checkeamos bloqueo de consejos $prefs = Model\User::getPreferences($project->owner); if ($prefs->tips) { if ($debug) { echo "Bloqueado por preferencias<hr />"; } continue; } // flag de aviso $avisado = false; // Consejos/avisos puntuales switch ($project->days) { // NO condicionales case 1: // Difunde, difunde, difunde // Difunde, difunde, difunde case 2: // Comienza por lo más próximo // Comienza por lo más próximo case 3: // Una acción a diario, por pequeña que sea // Una acción a diario, por pequeña que sea case 4: // Llama a todas las puertas // Llama a todas las puertas case 5: // Busca dónde está tu comunidad // Busca dónde está tu comunidad case 8: // Agradece en público e individualmente $template = 'tip_' . $project->days; if ($debug) { echo "Envío {$template}<br />"; } Send::toOwner($template, $project); break; // periodico condicional // periodico condicional case 6: // Publica novedades! // y se repite cada 6 días (fechas libres) mientras no haya posts // Publica novedades! // y se repite cada 6 días (fechas libres) mientras no haya posts case 12: case 18: case 24: case 30: case 36: // si ya hay novedades, nada if (Model\Blog::hasUpdates($project->id)) { if ($debug) { echo "Ya ha publicado novedades<br />"; } } else { if ($debug) { echo "Envío aviso de que no ha publicado novedades<br />"; } Send::toOwner('any_update', $project); $avisado = true; } break; // comprobación periódica pero solo un envío // comprobación periódica pero solo un envío case 7: // Apóyate en quienes te van apoyando , si más de 20 cofinanciadores // o en cuanto llegue a 20 backers (en fechas libres) // Apóyate en quienes te van apoyando , si más de 20 cofinanciadores // o en cuanto llegue a 20 backers (en fechas libres) case 14: case 17: case 21: case 24: case 27: // Si ya se mandó esta plantilla (al llegar a los 20 por primera vez) no se envía de nuevo $sql = "\n SELECT\n id\n FROM mail\n WHERE mail.email = :email\n AND mail.template = 46\n ORDER BY mail.date DESC\n LIMIT 1"; $query = Model\Project::query($sql, array(':email' => $project->user->email)); $sended = $query->fetchColumn(0); if (!$sended) { if ($project->num_investors >= 20) { if ($debug) { echo "Tiene 20 backers y no se le habia enviado aviso antes<br />"; } Send::toOwner('20_backers', $project); } else { if ($debug) { echo "No llega a los 20 backers<br />"; } } } else { if ($debug) { echo "Ya enviado<br />"; } } break; case 9: // Busca prescriptores e implícalos // si no tiene padrinos if ($project->patrons > 0) { if ($debug) { echo "Tiene padrino<br />"; } } else { if ($debug) { echo "No tiene padrino<br />"; } Send::toOwner('tip_9', $project); } break; case 10: // Luce tus recompensas y retornos // que no se envie a los que solo tienen recompensas de agradecimiento $thanksonly = true; // recompensas $rewards = Model\Project\Reward::getAll($project->id, 'individual', \LANG); foreach ($rewards as $rew) { if ($rew->icon != 'thanks') { $thanksonly = false; break; // ya salimos del bucle, no necesitamos más } } if ($thanksonly) { if ($debug) { echo "Solo tiene recompensas de agradecimiento<br />"; } } else { if ($debug) { echo "Tienen recompensas<br />"; } uasort($rewards, function ($a, $b) { if ($a->amount == $b->amount) { return 0; } return $a->amount > $b->amount ? 1 : -1; }); // sacar la primera y la última $lower = reset($rewards); $project->lower = $lower->reward; $higher = end($rewards); $project->higher = $higher->reward; Send::toOwner('tip_10', $project); } break; case 11: // Refresca tu mensaje de motivacion // si no tiene video motivacional if (empty($project->video)) { if ($debug) { echo "No tiene video motivacional<br />"; } Send::toOwner('tip_11', $project); } else { if ($debug) { echo "Tiene video motivacional<br />"; } } break; case 15: // Sigue los avances y calcula lo que falta // si no ha llegado al mínimo if ($project->invested < $project->mincost) { if ($debug) { echo "No ha llegado al mínimo<br />"; } Send::toOwner('tip_15', $project); } else { if ($debug) { echo "Ha llegado al mínimo<br />"; } } break; case 25: // No bajes la guardia! // si no ha llegado al mínimo if ($project->invested < $project->mincost) { if ($debug) { echo "No ha llegado al mínimo<br />"; } Send::toOwner('two_weeks', $project); } else { if ($debug) { echo "Ha llegado al mínimo<br />"; } } break; case 32: // Al proyecto le faltan 8 días para archivarse // si no ha llegado al mínimo if ($project->invested < $project->mincost) { if ($debug) { echo "No ha llegado al mínimo<br />"; } Send::toOwner('8_days', $project); } else { if ($debug) { echo "Ha llegado al mínimo<br />"; } } break; case 38: // Al proyecto le faltan 2 días para archivarse // si no ha llegado al mínimo pero está por encima del 70% if ($project->invested < $project->mincost && $project->percent >= 70) { if ($debug) { echo "No ha llegado al mínimo<br />"; } Send::toOwner('2_days', $project); } else { if ($debug) { echo "Ha llegado al mínimo o lleva menos de 70%<br />"; } } break; } // Avisos periodicos // si lleva más de 15 días: si no se han publicado novedades en la última semana // Ojo! que si no a enviado ninguna no lanza este sino la de cada 6 días if (!$avisado && $project->days > 15) { if ($debug) { echo "ya lleva una quincena de campaña, verificamos novedades<br />"; } // veamos si ya le avisamos hace una semana // Si ya se mandó esta plantilla (al llegar a los 20 por primera vez) no se envía de nuevo $sql = "\n SELECT\n id,\n DATE_FORMAT(\n from_unixtime(unix_timestamp(now()) - unix_timestamp(date))\n , '%j'\n ) as days\n FROM mail\n WHERE mail.email = :email\n AND mail.template = 23\n ORDER BY mail.date DESC\n LIMIT 1"; $query = Model\Project::query($sql, array(':email' => $project->user->email)); $lastsend = $query->fetchObject(); if (!$lastsend->id || $lastsend->days > 7) { // veamos cuanto hace de la última novedad $sql = "\n SELECT\n DATE_FORMAT(\n from_unixtime(unix_timestamp(now()) - unix_timestamp(date))\n , '%j'\n ) as days\n FROM post\n INNER JOIN blog\n ON post.blog = blog.id\n AND blog.type = 'project'\n AND blog.owner = :project\n WHERE post.publish = 1\n ORDER BY post.date DESC\n LIMIT 1"; $query = Model\Project::query($sql, array(':project' => $project->id)); $lastUpdate = $query->fetchColumn(0); if ($lastUpdate > 7) { if ($debug) { echo "Ultima novedad es de hace más de una semana<br />"; } Send::toOwner('no_updates', $project); } elseif (is_numeric($lastUpdate)) { if ($debug) { echo "Publicó novedad hace menos de una semana<br />"; } } else { if ($debug) { echo "No se ha publicado nada, recibirá el de cada 6 días<br />"; } } } else { if ($debug) { echo "Se le avisó por novedades hace menos de una semana<br />"; } } } if ($debug) { echo "<hr />"; } } if ($debug) { echo "<br />Auto-tips Listo!<hr />"; } return; }
public function projects($option = 'summary', $action = 'list', $id = null) { $user = $_SESSION['user']; $errors = array(); // verificación de proyectos y proyecto de trabajo list($project, $projects) = Dashboard\Projects::verifyProject($user, $action); // teniendo proyecto de trabajo, comprobar si el proyecto esta en estado de tener blog if ($option == 'updates') { $blog = Dashboard\Projects::verifyBlog($project); } // sacaexcel de cofinanciadores if ($option == 'rewards' && $action == 'table') { $response = new \Goteo\Controller\Sacaexcel(); return $response->index('investors', $project->id); } // ojo si no tiene retornos if ($option == 'commons' && empty($project->social_rewards)) { Message::Error('Este proyecto no tiene retornos colectivos'); throw new Redirection('/dashboard/projects/'); } // procesamiento de formularios if ($_SERVER['REQUEST_METHOD'] == 'POST') { switch ($option) { // gestionar retornos (o mensaje a los mensajeros) case 'messegers': case 'rewards': // sacamos del post el filtro y el orden if ($action == 'filter') { $_SESSION['dashboard-rewards-filter'] = isset($_POST['filter']) ? $_POST['filter'] : $_SESSION['dashboard-rewards-filter']; $_SESSION['dashboard-rewards-order'] = isset($_POST['order']) ? $_POST['order'] : $_SESSION['dashboard-rewards-order']; } //procesamos el envio de mails if ($action == 'message') { Dashboard\Projects::process_mailing($option, $project); // y lo devolvemos a donde estaba throw new Redirection('/dashboard/projects/' . $option); } break; // colaboraciones // colaboraciones case 'supports': if ($action == 'save') { $project = Dashboard\Projects::process_supports($project, $errors); } break; case 'updates': // verificación: si no llega blog correcto no lo procesamos if (empty($_POST['blog']) || $_POST['blog'] != $blog->id) { throw new Redirection('/dashboard/projects/summary'); } list($action, $id) = Dashboard\Projects::process_updates($action, $project, $errors); break; } } // SubControlador para add, edit, delete y list // devuelve $post en las acciones add y edit y $posts en delete y list // maneja por referencia $action, $posts y $errors if ($option == 'updates') { list($post, $posts) = Dashboard\Projects::prepare_updates($action, $id, $blog->id); } // view data basico para esta seccion $viewData = array('menu' => self::menu(), 'section' => __FUNCTION__, 'option' => $option, 'action' => $action, 'projects' => $projects, 'errors' => $errors); switch ($option) { case 'summary': // los datos json de invests y visitors_data $viewData['data'] = Dashboard\Projects::graph($project->id); break; // gestionar recompensas // gestionar recompensas case 'rewards': // recompensas ofrecidas $viewData['rewards'] = Model\Project\Reward::getAll($project->id, 'individual', LANG); // aportes para este proyecto $viewData['invests'] = Model\Invest::getAll($project->id); // ver por (esto son orden y filtros) $viewData['filter'] = $_SESSION['dashboard-rewards-filter']; $viewData['order'] = $_SESSION['dashboard-rewards-order']; break; // gestionar retornos // gestionar retornos case 'commons': $icons = Model\Icon::getAll('social'); foreach ($icons as $key => $icon) { $icons[$key] = $icon->name; } $viewData['icons'] = $icons; break; // listar mensajeadores // listar mensajeadores case 'messegers': $viewData['messegers'] = Model\Message::getMessegers($project->id); break; // editar colaboraciones // editar colaboraciones case 'supports': $viewData['types'] = Model\Project\Support::types(); // para mantener registros desplegados if ($_POST) { foreach ($_POST as $k => $v) { if (!empty($v) && preg_match('/support-(\\d+)-edit/', $k, $r)) { $viewData[$k] = true; break; } } } if (!empty($_POST['support-add'])) { $last = end($project->supports); if ($last !== false) { $viewData['support-' . $last->id . '-edit'] = true; } } $project->supports = Model\Project\Support::getAll($project->id); break; // publicar actualizaciones // publicar actualizaciones case 'updates': $viewData['blog'] = $blog; $viewData['posts'] = $posts; $viewData['post'] = $post; break; } $viewData['project'] = $project; return new View('view/dashboard/index.html.php', $viewData); }
/** * actualiza en la tabla los datos del proyecto * @param array $project->errors para guardar los errores de datos del formulario, los errores de proceso se guardan en $project->errors['process'] */ public function save(&$errors = array()) { if ($this->dontsave) { return false; } if (!$this->validate($errors)) { return false; } try { // fail para pasar por todo antes de devolver false $fail = false; // los nif sin guiones, espacios ni puntos $this->contract_nif = str_replace(array('_', '.', ' ', '-', ',', ')', '('), '', $this->contract_nif); $this->entity_cif = str_replace(array('_', '.', ' ', '-', ',', ')', '('), '', $this->entity_cif); // Image if (is_array($this->image) && !empty($this->image['name'])) { $image = new Image($this->image); if ($image->save($errors)) { $this->gallery[] = $image; $this->image = $image->id; /** * Guarda la relación NM en la tabla 'project_image'. */ if (!empty($image->id)) { self::query("REPLACE project_image (project, image) VALUES (:project, :image)", array(':project' => $this->id, ':image' => $image->id)); } } } $fields = array('contract_name', 'contract_nif', 'contract_email', 'contract_entity', 'contract_birthdate', 'entity_office', 'entity_name', 'entity_cif', 'phone', 'address', 'zipcode', 'location', 'country', 'secondary_address', 'post_address', 'post_zipcode', 'post_location', 'post_country', 'name', 'subtitle', 'image', 'description', 'motivation', 'video', 'video_usubs', 'about', 'goal', 'related', 'reward', 'keywords', 'media', 'media_usubs', 'currently', 'project_location', 'scope', 'resource', 'comment', 'evaluation'); $set = ''; $values = array(); foreach ($fields as $field) { if ($set != '') { $set .= ', '; } $set .= "{$field} = :{$field}"; $values[":{$field}"] = $this->{$field}; } // Solamente marcamos updated cuando se envia a revision desde el superform o el admin // $set .= ", updated = :updated"; // $values[':updated'] = date('Y-m-d'); $values[':id'] = $this->id; $sql = "UPDATE project SET " . $set . " WHERE id = :id"; if (!self::query($sql, $values)) { $errors[] = $sql . '<pre>' . print_r($values, 1) . '</pre>'; $fail = true; } // echo "$sql<br />"; // y aquí todas las tablas relacionadas // cada una con sus save, sus new y sus remove // quitar las que tiene y no vienen // añadir las que vienen y no tiene //categorias $tiene = Project\Category::get($this->id); $viene = $this->categories; $quita = array_diff_assoc($tiene, $viene); $guarda = array_diff_assoc($viene, $tiene); foreach ($quita as $key => $item) { $category = new Project\Category(array('id' => $item, 'project' => $this->id)); if (!$category->remove($errors)) { $fail = true; } } foreach ($guarda as $key => $item) { if (!$item->save($errors)) { $fail = true; } } // recuperamos las que le quedan si ha cambiado alguna if (!empty($quita) || !empty($guarda)) { $this->categories = Project\Category::get($this->id); } //skills $tiene = Project\Skill::get($this->id); $viene = $this->skills; $quita = array_diff_assoc($tiene, $viene); $guarda = array_diff_assoc($viene, $tiene); foreach ($quita as $key => $item) { $skill = new Project\Skill(array('id' => $item, 'project' => $this->id)); if (!$skill->remove($errors)) { $fail = true; } } foreach ($guarda as $key => $item) { if (!$item->save($errors)) { $fail = true; } } // recuperamos las que le quedan si ha cambiado alguna if (!empty($quita) || !empty($guarda)) { $this->skills = Project\Skill::get($this->id); } //costes $tiene = Project\Cost::getAll($this->id); $viene = $this->costs; $quita = array_diff_key($tiene, $viene); $guarda = array_diff_key($viene, $tiene); foreach ($quita as $key => $item) { if (!$item->remove($errors)) { $fail = true; } else { unset($tiene[$key]); } } foreach ($guarda as $key => $item) { if (!$item->save($errors)) { $fail = true; } } /* Ahora, los que tiene y vienen. Si el contenido es diferente, hay que guardarlo*/ foreach ($tiene as $key => $row) { // a ver la diferencia con el que viene if ($row != $viene[$key]) { if (!$viene[$key]->save($errors)) { $fail = true; } } } if (!empty($quita) || !empty($guarda)) { $this->costs = Project\Cost::getAll($this->id); } // recalculo de minmax $this->minmax(); //retornos colectivos $tiene = Project\Reward::getAll($this->id, 'social'); $viene = $this->social_rewards; $quita = array_diff_key($tiene, $viene); $guarda = array_diff_key($viene, $tiene); foreach ($quita as $key => $item) { if (!$item->remove($errors)) { $fail = true; } else { unset($tiene[$key]); } } foreach ($guarda as $key => $item) { if (!$item->save($errors)) { $fail = true; } } /* Ahora, los que tiene y vienen. Si el contenido es diferente, hay que guardarlo*/ foreach ($tiene as $key => $row) { // a ver la diferencia con el que viene if ($row != $viene[$key]) { if (!$viene[$key]->save($errors)) { $fail = true; } } } if (!empty($quita) || !empty($guarda)) { $this->social_rewards = Project\Reward::getAll($this->id, 'social'); } //recompenssas individuales $tiene = Project\Reward::getAll($this->id, 'individual'); $viene = $this->individual_rewards; $quita = array_diff_key($tiene, $viene); $guarda = array_diff_key($viene, $tiene); foreach ($quita as $key => $item) { if (!$item->remove($errors)) { $fail = true; } else { unset($tiene[$key]); } } foreach ($guarda as $key => $item) { if (!$item->save($errors)) { $fail = true; } } /* Ahora, los que tiene y vienen. Si el contenido es diferente, hay que guardarlo*/ foreach ($tiene as $key => $row) { // a ver la diferencia con el que viene if ($row != $viene[$key]) { if (!$viene[$key]->save($errors)) { $fail = true; } } } if (!empty($quita) || !empty($guarda)) { $this->individual_rewards = Project\Reward::getAll($this->id, 'individual'); } // colaboraciones $tiene = Project\Support::getAll($this->id); $viene = $this->supports; $quita = array_diff_key($tiene, $viene); // quitar los que tiene y no viene $guarda = array_diff_key($viene, $tiene); // añadir los que viene y no tiene foreach ($quita as $key => $item) { if (!$item->remove($errors)) { $fail = true; } else { unset($tiene[$key]); } } foreach ($guarda as $key => $item) { if (!$item->save($errors)) { $fail = true; } } /* Ahora, los que tiene y vienen. Si el contenido es diferente, hay que guardarlo*/ foreach ($tiene as $key => $row) { // a ver la diferencia con el que viene if ($row != $viene[$key]) { if (!$viene[$key]->save($errors)) { $fail = true; } } } if (!empty($quita) || !empty($guarda)) { $this->supports = Project\Support::getAll($this->id); } //listo return !$fail; } catch (\PDOException $e) { $errors[] = Text::_('No se ha grabado correctamente. ') . $e->getMessage(); //Text::get('save-project-fail'); return false; } }