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); }
public function index($project = null) { if (empty($project)) { throw new Redirection('/discover', Redirection::TEMPORARY); } $message = ''; $projectData = Model\Project::get($project); $methods = static::_methods(); // si no está en campaña no pueden esta qui ni de coña if ($projectData->status != 3) { throw new Redirection('/project/' . $project, Redirection::TEMPORARY); } if ($_SERVER['REQUEST_METHOD'] == 'POST') { $errors = array(); $los_datos = $_POST; $method = \strtolower($_POST['method']); if (!isset($methods[$method])) { Message::Error(Text::get('invest-method-error')); throw new Redirection(SEC_URL . "/project/{$project}/invest/?confirm=fail", Redirection::TEMPORARY); } if (empty($_POST['amount'])) { Message::Error(Text::get('invest-amount-error')); throw new Redirection(SEC_URL . "/project/{$project}/invest/?confirm=fail", Redirection::TEMPORARY); } // dirección de envio para las recompensas // o datoas fiscales del donativo $address = array('name' => $_POST['fullname'], 'nif' => $_POST['nif'], 'address' => $_POST['address'], 'zipcode' => $_POST['zipcode'], 'location' => $_POST['location'], 'country' => $_POST['country']); if ($projectData->owner == $_SESSION['user']->id) { Message::Error(Text::get('invest-owner-error')); throw new Redirection(SEC_URL . "/project/{$project}/invest/?confirm=fail", Redirection::TEMPORARY); } // añadir recompensas que ha elegido $chosen = $_POST['selected_reward']; if ($chosen == 0) { // renuncia a las recompensas, bien por el/ella $resign = true; $reward = false; } else { // ya no se aplica esto de recompensa es de tipo Reconocimiento para donativo $resign = false; $reward = true; } // insertamos los datos personales del usuario si no tiene registro aun Model\User::setPersonal($_SESSION['user']->id, $address, false); $invest = new Model\Invest(array('amount' => $_POST['amount'], 'user' => $_SESSION['user']->id, 'project' => $project, 'method' => $method, 'status' => '-1', 'invested' => date('Y-m-d'), 'anonymous' => $_POST['anonymous'], 'resign' => $resign)); if ($reward) { $invest->rewards = array($chosen); } $invest->address = (object) $address; if ($invest->save($errors)) { $invest->urlOK = SEC_URL . "/invest/confirmed/{$project}/{$invest->id}"; $invest->urlNOK = SEC_URL . "/invest/fail/{$project}/{$invest->id}"; Model\Invest::setDetail($invest->id, 'init', 'Se ha creado el registro de aporte, el usuario ha clickado el boton de tpv o paypal. Proceso controller/invest'); switch ($method) { case 'tpv': // redireccion al tpv if (Tpv::preapproval($invest, $errors)) { die; } else { Message::Error(Text::get('invest-tpv-error_fatal')); } break; case 'paypal': // Petición de preapproval y redirección a paypal if (Paypal::preapproval($invest, $errors)) { die; } else { Message::Error(Text::get('invest-paypal-error_fatal')); } break; case 'cash': // En betatest aceptamos cash para pruebas if (GOTEO_ENV != 'real') { $invest->setStatus('1'); throw new Redirection($invest->urlOK); } else { throw new Redirection('/'); } break; } } else { Message::Error(Text::get('invest-create-error')); } } else { Message::Error(Text::get('invest-data-error')); } throw new Redirection("/project/{$project}/invest/?confirm=fail"); }
public function execute() { if (!\defined('CRON_EXEC')) { @mail(\GOTEO_FAIL_MAIL, 'Se ha lanzado MANUALMENTE el cron ' . __FUNCTION__ . ' en ' . SITE_URL, 'Se ha lanzado manualmente el cron ' . __FUNCTION__ . ' en ' . SITE_URL . ' a las ' . date('H:i:s') . ' Usuario ' . $_SESSION['user']->id); echo 'Lanzamiento manual a las ' . date('H:i:s') . ' <br />'; } else { echo 'Lanzamiento automatico a las ' . date('H:i:s') . ' <br />'; } // a ver si existe el bloqueo $block_file = GOTEO_PATH . 'logs/cron-' . __FUNCTION__ . '.block'; if (file_exists($block_file)) { echo 'Ya existe un archivo de log ' . date('Ymd') . '_' . __FUNCTION__ . '.log<br />'; $block_content = \file_get_contents($block_file); echo 'El contenido del bloqueo es: ' . $block_content; // lo escribimos en el log $log_file = GOTEO_PATH . 'logs/cron/' . date('Ymd') . '_' . __FUNCTION__ . '.log'; \file_put_contents($log_file, \ob_get_contents(), FILE_APPEND); \chmod($log_file, 0777); /* @mail(\GOTEO_FAIL_MAIL, 'Cron '. __FUNCTION__ .' bloqueado en ' . SITE_URL, 'Se ha encontrado con que el cron '. __FUNCTION__ .' está bloqueado el '.date('d-m-Y').' a las ' . date ('H:i:s') . ' El contenido del bloqueo es: '. $block_content); */ die; } else { $block = 'Bloqueo del ' . $block_file . ' activado el ' . date('d-m-Y') . ' a las ' . date('H:i:s') . '<br />'; if (\file_put_contents($block_file, $block, FILE_APPEND)) { \chmod($block_file, 0777); echo $block; } else { echo 'No se ha podido crear el archivo de bloqueo<br />'; @mail(\GOTEO_FAIL_MAIL, 'Cron ' . __FUNCTION__ . ' no se ha podido bloquear en ' . SITE_URL, 'No se ha podido crear el archivo ' . $block_file . ' el ' . date('d-m-Y') . ' a las ' . date('H:i:s')); } } echo '<hr />'; // debug para supervisar en las fechas clave // $debug = ($_GET['debug'] == 'debug') ? true : false; $debug = true; // revision de proyectos: dias, conseguido y cambios de estado // proyectos en campaña, // (publicados hace más de 40 días que no tengan fecha de pase) // o (publicados hace mas de 80 días que no tengan fecha de exito) $projects = Model\Project::getActive(); if ($debug) { echo 'Comenzamos con los proyectos en campaña (esto está en ' . \LANG . ')<br /><br />'; } foreach ($projects as $project) { if ($debug) { echo 'Proyecto ' . $project->name . '<br />'; } // a ver si tiene cuenta paypal $projectAccount = Model\Project\Account::get($project->id); /* if (empty($projectAccount->paypal)) { if ($debug) echo 'No tiene cuenta PayPal<br />'; // Evento Feed solamente si automático if (\defined('CRON_EXEC')) { $log = new Feed(); $log->setTarget($project->id); $log->populate('proyecto sin cuenta paypal (cron)', '/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); // mail de aviso $mailHandler = new Mail(); $mailHandler->to = \GOTEO_CONTACT_MAIL; $mailHandler->toName = 'Goteo.org'; $mailHandler->subject = 'El proyecto '.$project->name.' no tiene cuenta PayPal'; $mailHandler->content = 'Hola Goteo, el proyecto '.$project->name.' no tiene cuenta PayPal y el proceso automatico no podrá tratar los preaprovals al final de ronda.'; $mailHandler->html = false; $mailHandler->template = null; $mailHandler->send(); unset($mailHandler); $task = new Model\Task(); $task->node = \GOTEO_NODE; $task->text = "Poner la cuenta PayPal al proyecto <strong>{$project->name}</strong> urgentemente!"; $task->url = "/admin/projects/accounts/{$project->id}"; $task->done = null; $task->saveUnique(); } } */ $log_text = null; if ($debug) { echo 'Minimo: ' . $project->mincost . ' ¥ <br />'; } $execute = false; $cancelAll = false; if ($debug) { echo 'Obtenido: ' . $project->amount . ' ¥<br />'; } // porcentaje alcanzado if ($project->mincost > 0) { $per_amount = \floor($project->amount / $project->mincost * 100); } else { $per_amount = 0; } if ($debug) { echo 'Ha alcanzado el ' . $per_amount . ' % del minimo<br />'; } // los dias que lleva el proyecto (ojo que los financiados llevaran mas de 80 dias) $days = $project->daysActive(); if ($debug) { echo 'Lleva ' . $days . ' dias desde la publicacion<br />'; } /* Verificar si enviamos aviso */ $rest = $project->days; $round = $project->round; if ($debug) { echo 'Quedan ' . $rest . ' dias para el final de la ' . $round . 'a ronda<br />'; } // a los 5, 3, 2, y 1 dia para finalizar ronda if ($round > 0 && in_array((int) $rest, array(5, 3, 2, 1))) { if ($debug) { echo 'Feed publico cuando quedan 5, 3, 2, 1 dias<br />'; } // Evento Feed solo si ejecucion automática if (\defined('CRON_EXEC')) { $log = new Feed(); $log->setTarget($project->id); $log->populate('proyecto próximo a finalizar ronda (cron)', '/admin/projects', Text::html('feed-project_runout', Feed::item('project', $project->name, $project->id), $rest, $round)); $log->doAdmin('project'); // evento público $log->title = $project->name; $log->url = null; $log->doPublic('projects'); unset($log); } } // (financiado a los 80 o cancelado si a los 40 no llega al minimo) // si ha llegado a los 40 dias: mínimo-> ejecutar ; no minimo proyecto y todos los preapprovals cancelados // (Funded at 80 or canceled if the 40 does not reach the minimum) // If it has reached 40 days: minimum-> execute; no minimum project and canceled all preapprovals if ($days >= 40) { // si no ha alcanzado el mínimo, pasa a estado caducado // If you have not reached the minimum, goes into Expired if ($project->amount < $project->mincost) { if ($debug) { echo 'Ha llegado a los 40 dias de campaña sin conseguir el minimo, no pasa a segunda ronda<br />'; } echo $project->name . ': ha recaudado ' . $project->amount . ', ' . $per_amount . '% de ' . $project->mincost . '/' . $project->maxcost . '<br />'; echo 'No ha conseguido el minimo, cancelamos todos los aportes y lo caducamos:'; $cancelAll = true; $errors = array(); if ($project->fail($errors)) { $log_text = Text::_('El proyecto %s ha %s obteniendo %s'); } else { @mail(\GOTEO_FAIL_MAIL, 'Fallo al archivar ' . SITE_URL, 'Fallo al marcar el proyecto ' . $project->name . ' como archivado ' . implode(',', $errors)); echo 'ERROR::' . implode(',', $errors); $log_text = Text::_('El proyecto %s ha fallado al, %s obteniendo %s'); } echo '<br />'; // Evento Feed solo si ejecucion automatica if (\defined('CRON_EXEC')) { $log = new Feed(); $log->setTarget($project->id); $log->populate('proyecto archivado (cron)', '/admin/projects', \vsprintf($log_text, array(Feed::item('project', $project->name, $project->id), Feed::item('relevant', 'caducado sin éxito'), Feed::item('money', $project->amount . ' ¥ (' . $per_amount . '%) de aportes sobre minimo')))); $log->doAdmin('project'); // evento público $log->populate($project->name, null, Text::html('feed-project_fail', Feed::item('project', $project->name, $project->id), $project->amount, $per_amount)); $log->doPublic('projects'); unset($log); //Email de proyecto fallido al autor Cron\Send::toOwner('fail', $project); //Email de proyecto fallido a los inversores Cron\Send::toInvestors('fail', $project); } echo '<br />'; } else { // tiene hasta 80 días para conseguir el óptimo (o más) // Has up to 80 days for optimum (or more) if ($days >= 80) { if ($debug) { echo 'Ha llegado a los 80 dias de campaña (final de segunda ronda)<br />'; } echo $project->name . ': ha recaudado ' . $project->amount . ', ' . $per_amount . '% de ' . $project->mincost . '/' . $project->maxcost . '<br />'; echo 'Ha llegado a los 80 días: financiado. '; $execute = true; // ejecutar los cargos de la segunda ronda $errors = array(); if ($project->succeed($errors)) { $log_text = Text::_('El proyecto %s ha sido %s obteniendo %s'); } else { @mail(\GOTEO_FAIL_MAIL, 'Fallo al marcar financiado ' . SITE_URL, 'Fallo al marcar el proyecto ' . $project->name . ' como financiado ' . implode(',', $errors)); echo 'ERROR::' . implode(',', $errors); $log_text = Text::_('El proyecto %s ha fallado al ser, %s obteniendo %s'); } // Evento Feed y mails solo si ejecucion automatica if (\defined('CRON_EXEC')) { $log = new Feed(); $log->setTarget($project->id); $log->populate('proyecto supera segunda ronda (cron)', '/admin/projects', \vsprintf($log_text, array(Feed::item('project', $project->name, $project->id), Feed::item('relevant', 'financiado'), Feed::item('money', $project->amount . ' ¥ (' . \round($per_amount) . '%) de aportes sobre minimo')))); $log->doAdmin('project'); // evento público $log->populate($project->name, null, Text::html('feed-project_finish', Feed::item('project', $project->name, $project->id), $project->amount, \round($per_amount))); $log->doPublic('projects'); unset($log); //Email de proyecto final segunda ronda al autor Cron\Send::toOwner('r2_pass', $project); //Email de proyecto final segunda ronda a los inversores Cron\Send::toInvestors('r2_pass', $project); // Tareas para gestionar // calculamos fecha de passed+90 días $passtime = strtotime($project->passed); $limsec = date('d/m/Y', \mktime(0, 0, 0, date('m', $passtime), date('d', $passtime) + 89, date('Y', $passtime))); /* * Ya no hacemos pagos secundarios mediante sistema $task = new Model\Task(); $task->node = \GOTEO_NODE; $task->text = "Hacer los pagos secundarios al proyecto <strong>{$project->name}</strong> antes del día <strong>{$limsec}</strong>"; $task->url = "/admin/accounts/?projects={$project->id}"; $task->done = null; $task->save(); */ // y preparar contrato $task = new Model\Task(); $task->node = \GOTEO_NODE; $task->text = date('d/m/Y') . ": Enviar datos contrato <strong>{$project->name}</strong>, {$project->user->name}"; //@TODO enlace a gestión de contrato $task->url = "/admin/projects?proj_name={$project->name}"; $task->done = null; $task->saveUnique(); // + mail a mercè @mail(\GOTEO_CONTACT_MAIL, 'Preparar contrato ' . $project->name, 'El proyecto ' . $project->name . ' ha pasado la primera ronda, enviarle los datos de contrato. Se ha creado una tarea para esto.'); } echo '<br />'; } elseif (empty($project->passed)) { if ($debug) { echo 'Ha llegado a los 40 dias de campaña, pasa a segunda ronda<br />'; } echo $project->name . ': ha recaudado ' . $project->amount . ', ' . $per_amount . '% de ' . $project->mincost . '/' . $project->maxcost . '<br />'; echo 'El proyecto supera la primera ronda: marcamos fecha'; $execute = true; // ejecutar los cargos de la primera ronda $errors = array(); if ($project->passed($errors)) { // se crea el registro de contrato // Recording contract is created if (Model\Contract::create($project->id, $errors)) { echo ' -> Ok:: se ha creado el registro de contrato'; } else { @mail(\GOTEO_FAIL_MAIL, 'Fallo al crear registro de contrato ' . SITE_URL, 'Fallo al crear registro de contrato para el proyecto ' . $project->name . ': ' . implode(',', $errors)); echo ' -> semi-Ok: se ha actualiuzado el estado del proyecto pero ha fallado al crear el registro de contrato. ERROR: ' . implode(',', $errors); } } else { @mail(\GOTEO_FAIL_MAIL, 'Fallo al marcar fecha de paso a segunda ronda ' . SITE_URL, 'Fallo al marcar la fecha de paso a segunda ronda para el proyecto ' . $project->name . ': ' . implode(',', $errors)); echo ' -> ERROR::' . implode(',', $errors); } echo '<br />'; // Evento Feed solo si ejecucion automatica if (\defined('CRON_EXEC')) { $log = new Feed(); $log->setTarget($project->id); $log->populate('proyecto supera primera ronda (cron)', '/admin/projects', \vsprintf('El proyecto %s %s en segunda ronda obteniendo %s', array(Feed::item('project', $project->name, $project->id), Feed::item('relevant', 'continua en campaña'), Feed::item('money', $project->amount . ' ¥ (' . \number_format($per_amount, 2) . '%) de aportes sobre minimo')))); $log->doAdmin('project'); // evento público $log->populate($project->name, null, Text::html('feed-project_goon', Feed::item('project', $project->name, $project->id), $project->amount, \round($per_amount))); $log->doPublic('projects'); unset($log); if ($debug) { echo 'Email al autor y a los cofinanciadores<br />'; } // Email de proyecto pasa a segunda ronda al autor Cron\Send::toOwner('r1_pass', $project); //Email de proyecto pasa a segunda ronda a los inversores Cron\Send::toInvestors('r1_pass', $project); // Tarea para hacer los pagos $task = new Model\Task(); $task->node = \GOTEO_NODE; $task->text = date('d/m/Y') . ": Pagar a <strong>{$project->name}</strong>, {$project->user->name}"; $task->url = "/admin/projects/report/{$project->id}"; $task->done = null; $task->saveUnique(); // + mail a susana @mail('*****@*****.**', 'Pagar al proyecto ' . $project->name, 'El proyecto ' . $project->name . ' ha terminado la segunda ronda, hacer los pagos. Se ha creado una tarea para esto.'); } } else { if ($debug) { echo 'Lleva más de 40 dias de campaña, debe estar en segunda ronda con fecha marcada<br />'; } if ($debug) { echo $project->name . ': lleva recaudado ' . $project->amount . ', ' . $per_amount . '% de ' . $project->mincost . '/' . $project->maxcost . ' y paso a segunda ronda el ' . $project->passed . '<br />'; } } } } // si hay que ejecutar o cancelar if ($cancelAll || $execute) { if ($debug) { echo '::::::Comienza tratamiento de aportes:::::::<br />'; } if ($debug) { echo 'Execute=' . (string) $execute . ' CancelAll=' . (string) $cancelAll . '<br />'; } // tratamiento de aportes penddientes $query = \Goteo\Core\Model::query("\n SELECT *\n FROM invest\n WHERE invest.project = ?\n AND (invest.status = 0\n OR (invest.method = 'tpv'\n AND invest.status = 1\n )\n OR (invest.method = 'cash'\n AND invest.status = 1\n )\n )\n AND (invest.campaign IS NULL OR invest.campaign = 0)\n ", array($project->id)); $project->invests = $query->fetchAll(\PDO::FETCH_CLASS, '\\Goteo\\Model\\Invest'); foreach ($project->invests as $key => $invest) { $errors = array(); $log_text = null; $userData = Model\User::getMini($invest->user); if ($invest->invested == date('Y-m-d')) { if ($debug) { echo 'Aporte ' . $invest->id . ' es de hoy.<br />'; } } elseif ($invest->method != 'cash' && empty($invest->preapproval)) { //si no tiene preaproval, cancelar //echo 'Aporte ' . $invest->id . ' cancelado por no tener preapproval.<br />'; //$invest->cancel(); //Model\Invest::setDetail($invest->id, 'no-preapproval', 'Aporte cancelado porque no tiene preapproval. Proceso cron/execute'); //continue; } if ($cancelAll) { if ($debug) { echo 'Cancelar todo<br />'; } switch ($invest->method) { // case 'paypal': // $err = array(); // if (Paypal::cancelPreapproval($invest, $err, true)) { // $log_text = Text::_("Se ha cancelado aporte y preapproval de %s de %s mediante PayPal (id: %s) al proyecto %s del dia %s"); // } else { // $txt_errors = implode('; ', $err); // $log_text = Text::_("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; // } // break; case 'axes': if ($invest->cancel(true)) { $log_text = Text::_("Contribution is canceled"); } else { $log_text = Text::_("Failed to cancel"); } break; case 'tpv': // se habre la operación en optra ventana $err = array(); if (Tpv::cancelPreapproval($invest, $err, true)) { $log_text = Text::_("Se ha anulado el cargo tpv de %s de %s mediante TPV (id: %s) al proyecto %s del dia %s"); } else { $txt_errors = implode('; ', $err); $log_text = Text::_("Ha fallado al anular el 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(true)) { $log_text = Text::_("Se ha cancelado aporte manual de %s de %s (id: %s) al proyecto %s del dia %s"); } else { $log_text = Text::_("Ha fallado al cancelar el aporte manual de %s de %s (id: %s) al proyecto %s del dia %s. "); } break; } // Evento Feed admin $log = new Feed(); $log->setTarget($project->id); $log->populate('Preapproval cancelado por proyecto archivado (cron)', '/admin/invests', \vsprintf($log_text, array(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(); unset($log); echo 'Aporte ' . $invest->id . ' cancelado por proyecto caducado.<br />'; $invest->setStatus('4'); Model\Invest::setDetail($invest->id, 'project-expired', 'Aporte marcado como caducado porque el proyecto no ha tenido exito. Proceso cron/execute'); continue; } // si hay que ejecutar if ($execute && empty($invest->payment)) { if ($debug) { echo 'Ejecutando aporte ' . $invest->id . ' [' . $invest->method . ']'; } switch ($invest->method) { /* cronではなく管理画面から手動で(admin/invests/dopay) case 'axes': $err = array(); if ($invest->setPayment(date("YmdHis"))) { $invest->setStatus(1); $log_text = Text::_("Has been executed under its %s %s contribution via Axes (id:%s) to the project %s %s of the day"); if ($debug) echo ' -> Ok'; Model\Invest::setDetail($invest->id, 'executed', 'Preapproval has been executed, has initiated the chained payment. Process cron / execute'); // si era incidencia la desmarcamos if ($invest->issue) { Model\Invest::unsetIssue($invest->id); Model\Invest::setDetail($invest->id, 'issue-solved', 'The incidence has been resolved upon success by the automatic process'); } } break;*/ case 'paypal': if (empty($projectAccount->paypal)) { if ($debug) { echo '<br />El proyecto ' . $project->name . ' no tiene cuenta paypal.<br />'; } Model\Invest::setDetail($invest->id, 'no-paypal-account', 'El proyecto no tiene cuenta paypal en el momento de ejecutar el preapproval. Proceso cron/execute'); break; } $invest->account = $projectAccount->paypal; $err = array(); if (Paypal::pay($invest, $err)) { $log_text = Text::_("Se ha ejecutado el cargo a %s por su aporte de %s mediante PayPal (id: %s) al proyecto %s del dia %s"); if ($debug) { echo ' -> Ok'; } Model\Invest::setDetail($invest->id, 'executed', 'Se ha ejecutado el preapproval, ha iniciado el pago encadenado. Proceso cron/execute'); // 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 ejecutarse correctamente en el proceso automático'); } } else { $txt_errors = implode('; ', $err); echo 'Aporte ' . $invest->id . ': Fallo al ejecutar cargo paypal: ' . $txt_errors . '<br />'; @mail(\GOTEO_FAIL_MAIL, 'Fallo al ejecutar cargo Paypal ' . SITE_URL, 'Aporte ' . $invest->id . ': Fallo al ejecutar cargo paypal: ' . $txt_errors); if ($debug) { echo ' -> ERROR!!'; } Model\Invest::setDetail($invest->id, 'execution-failed', 'Fallo al ejecutar el preapproval, no ha iniciado el pago encadenado: ' . $txt_errors . '. Proceso cron/execute'); // Notifiacion de incidencia al usuario // Obtenemos la plantilla para asunto y contenido $template = Template::get(37); // Sustituimos los datos $subject = str_replace('%PROJECTNAME%', $project->name, $template->title); $search = array('%USERNAME%', '%PROJECTNAME%', '%PROJECTURL%', '%AMOUNT%', '%DETAILS%'); $replace = array($userData->name, $project->name, SITE_URL . '/project/' . $project->id, $invest->amount, ''); $content = \str_replace($search, $replace, $template->text); // iniciamos mail $mailHandler = new Mail(); $mailHandler->from = GOTEO_CONTACT_MAIL; $mailHandler->to = $userData->email; $mailHandler->toName = $userData->name; $mailHandler->subject = $subject; $mailHandler->content = $content; $mailHandler->html = true; $mailHandler->template = $template->id; if ($mailHandler->send()) { Model\Invest::setDetail($invest->id, 'issue-notified', "Se ha notificado la incidencia al usuario"); } else { Model\Invest::setDetail($invest->id, 'issue-notify-failed', "Ha fallado al enviar el mail de notificacion de la incidencia al usuario"); @mail(\GOTEO_FAIL_MAIL, 'Fallo al enviar email de notificacion de incidencia PayPal' . SITE_URL, 'Fallo al enviar email de notificacion de incidencia PayPal: <pre>' . print_r($mailHandler, 1) . '</pre>'); } } break; case 'tpv': // los cargos con este tpv vienen ejecutados de base if ($debug) { echo ' -> Ok'; } /* $err = array(); if (Tpv::pay($invest, $err)) { echo 'Cargo sermepa correcto'; $log_text = "Se ha ejecutado el cargo a %s por su aporte de %s mediante TPV (id: %s) al proyecto %s del dia %s"; } else { $txt_errors = implode('; ', $err); echo 'Fallo al ejecutar cargo sermepa: ' . $txt_errors; $log_text = "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': // los cargos manuales no los modificamos if ($debug) { echo ' Cash, nada que hacer -> Ok'; } break; } if ($debug) { echo '<br />'; } if (!empty($log_text)) { // Evento Feed $log = new Feed(); $log->setTarget($project->id); $log->populate('Cargo ejecutado (cron)', '/admin/invests', \vsprintf($log_text, array(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(); if ($debug) { echo $log->html . '<br />'; } unset($log); } if ($debug) { echo 'Aporte ' . $invest->id . ' tratado<br />'; } } } if ($debug) { echo '::Fin tratamiento aportes<br />'; } } if ($debug) { echo 'Fin tratamiento Proyecto ' . $project->name . '<hr />'; } } // checkeamos campañas activas //$campaigns = Model\Call::getActive(4); $campaigns = array(); foreach ($campaigns as $campaign) { $errors = array(); // tiene que tener presupuesto if (empty($campaign->amount)) { continue; } // si le quedan cero // -> terminar la campaña exitosamente if ($campaign->rest == 0 && !empty($campaign->amount)) { echo 'La convocatoria ' . $campaign->name . ': '; if ($campaign->checkSuccess($errors)) { if ($campaign->succeed($errors)) { echo 'Ha terminado exitosamente.<br />'; $log = new Feed(); $log->setTarget($campaign->id, 'call'); $log->unique = true; $log->populate('Campaña terminada (cron)', '/admin/calls/' . $campaign->id . '?rest=' . $amount, \vsprintf('La campaña %s ha terminado con exito', array(Feed::item('call', $campaign->name, $campaign->id)))); $log->doAdmin('call'); $log->populate($campaign->name, '/call/' . $campaign->id . '?rest=' . $amount, \vsprintf('La campaña %s ha terminado con éxito', array(Feed::item('call', $campaign->name, $campaign->id))), $call->logo); $log->doPublic('projects'); unset($log); } else { echo 'Ha fallado al marcar exitosa.<br />' . implode('<br />', $errors); } } else { echo 'Le Queda algun proyecto en primera ronda.<br />'; } } } // desbloqueamos if (unlink($block_file)) { echo 'Cron ' . __FUNCTION__ . ' desbloqueado<br />'; } else { echo 'ALERT! Cron ' . __FUNCTION__ . ' no se ha podido desbloquear<br />'; if (file_exists($block_file)) { echo 'El archivo ' . $block_file . ' aun existe!<br />'; } else { echo 'No hay archivo de bloqueo ' . $block_file . '!<br />'; } } // recogemos el buffer para grabar el log $log_file = GOTEO_PATH . 'logs/cron/' . date('Ymd') . '_' . __FUNCTION__ . '.log'; \file_put_contents($log_file, \ob_get_contents(), FILE_APPEND); \chmod($log_file, 0777); }