public function close($id) { try { $user = User::find(Session::uid()); if (!$user->getId()) { throw new Exception('You have to be logged in to access user info!'); } $budget_id = (int) $id; $budget = new Budget(); if (!$budget->loadById($budget_id)) { throw new Exception('Invalid budget id'); } if ($budget->active != 1) { throw new Exception('This budget is already closed.'); } if ($user->getId() != $budget->receiver_id && $budget->giver_id != $user->getId()) { throw new Exception('Not enough rights'); } $budgetGiver = new User(); if (!$budgetGiver->findUserById($budget->giver_id)) { throw new Exception('Invalid giver id.'); } $budgetReceiver = new User(); if (!$budgetReceiver->findUserById($budget->receiver_id)) { throw new Exception('Invalid receiver id.'); } // all the child budgets are closed ? $childrenNotClosed = $budget->getChildrenNotClosed($budget->id); if ($childrenNotClosed != 0) { throw new Exception("This budget has one or more sub-allocated budget that are still active. " . "You may not close out this budget until the other budgets are closed out."); } // all the budgeted jobs are paid ? $feeAmountNotPaid = $this->getSumOfFeeNotPaidByBudget($budget->id); if ($feeAmountNotPaid !== null) { throw new Exception('Some fees are not paid.'); } $remainingFunds = $budget->getRemainingFunds(); if ($remainingFunds >= 0) { $budget->original_amount = $budget->amount; $budget->amount = $budget->original_amount - $remainingFunds; $budget->active = 0; $budgetReceiver->updateBudget(-$remainingFunds, $budget->id, false); $this->closeOutBudgetSource($remainingFunds, $budget, $budgetReceiver, $budgetGiver); if (!$budget->save('id')) { throw new Exception('Error in update budget.'); } } else { if ($user->getId() == $budget->receiver_id) { throw new Exception('Your budget is spent. Please contact the grantor (' . $budgetGiver->getNickname() . ') for additional funds.'); } $budget->original_amount = $budget->amount; $budget->amount = $budget->original_amount - $remainingFunds; $budget->active = 0; $budgetReceiver->updateBudget(-$remainingFunds, $budget->id, false); $this->closeOutBudgetSource($remainingFunds, $budget, $budgetReceiver, $budgetGiver); if (!$budget->save('id')) { throw new Exception('Error in update budget.'); } } $this->setOutput(array('success' => true, 'message' => 'Budget closed')); } catch (Exception $e) { return $this->setOutput(array('success' => false, 'message' => $e->getMessage())); } }
public function payBonus($id) { $this->view = null; try { $is_runner = isset($_SESSION['is_runner']) ? $_SESSION['is_runner'] : 0; $is_payer = isset($_SESSION['is_payer']) ? $_SESSION['is_payer'] : 0; // user must be logged in if (!Session::uid() || !$is_runner && !$is_payer) { throw new Exception('error: unauthorized'); } $giver = User::find(Session::uid()); $budget = $giver->getBudget(); // validate required fields if (empty($_POST['budget']) || empty($_POST['amount'])) { throw new Exception('error: args'); } $budget_source_combo = (int) $_POST['budget']; $budgetSource = new Budget(); if (!$budgetSource->loadById($budget_source_combo)) { throw new Exception('Invalid budget!'); } $amount = floatval($_POST['amount']); $stringAmount = number_format($amount, 2); $receiver = User::find($id); $reason = $_POST['reason']; $remainingFunds = $budgetSource->getRemainingFunds(); if (!($amount <= $budget && $amount <= $remainingFunds)) { throw new Exception('You do not have enough budget available to pay this bonus.'); } if (!$this->payBonusToUser($receiver->getId(), $amount, $reason, $budget_source_combo)) { throw new Exception('There was a problem while processing the payment.'); } // deduct amount from balance $giver->updateBudget(-$amount, $budget_source_combo); Utils::sendTemplateEmail($receiver->getUsername(), 'bonus_received', array('amount' => $stringAmount, 'reason' => $reason)); Utils::systemNotification('@' . $receiver->getNickname() . ' received a bonus of $' . $stringAmount); echo json_encode(array('success' => true, 'message' => 'Paid ' . $receiver->getNickname() . ' a bonus of $' . $stringAmount)); } catch (Exception $e) { echo json_encode(array('success' => false, 'message' => $e->getMessage())); } }
public function updateBudget($amount, $budget_id = 0, $budgetDepletedMessage = true) { $budgetDepletedSent = false; if ($budget_id > 0) { $budget = new Budget(); if ($budget->loadById($budget_id)) { $remainingFunds = $budget->getRemainingFunds(); $budget->remaining = $remainingFunds; $budget->save("id"); if ($remainingFunds <= 0 && $budgetDepletedMessage == true) { $runnerNickname = $this->getNickname(); $subject = "Depleted - Budget " . $budget_id . " (For " . $budget->reason . ")"; $link = SECURE_SERVER_URL . "team?showUser="******"&tab=tabBudgetHistory"; $body = '<p>Hi ' . $runnerNickname . '</p>'; $body .= "<p>Budget " . $budget_id . " for " . $budget->reason . "<br/> is now depleted.</p>"; $body .= '<p>If your budget has gone under 0.00, you will need to ask the user who ' . 'granted you the Budget to close out this budget for you.</p>'; $body .= '<p>To go to the Team Page, click <a href="' . $link . '">here</a></p>'; $body .= '<p>- Worklist.net</p>'; $plain = 'Hi ' . $runnerNickname . '\\n\\n'; $plain .= "Budget " . $budget_id . " for " . $budget->reason . "\n is now depleted.\n\n"; $plain .= 'If your budget has gone under 0.00, you will need to ask the user who ' . 'granted you the Budget to close out this budget for you.\\n\\n'; $plain .= 'To go to the Team Page, click ' . $link . "\n\n"; $plain .= '- Worklist.net\\n\\n'; if (!Utils::send_email($this->getUsername(), $subject, $body, $plain)) { error_log("User.class.php: Utils::send_email failed on depleted Runner warning"); } $budgetDepletedSent = true; } } else { error_log("User.class.php: Utils::send_email failed on depleted budget Runner warning - invalid budget id:" . $budget_id); } } $this->setBudget($this->setRemainingFunds()); $this->save(); }
public function edit($worklist_id = 0) { if (isset($_POST['api_key'])) { Utils::validateAPIKey(); $user = User::find($_POST['creator']); $userId = $user->getId(); } else { Utils::checkLogin(); $userId = Session::uid(); $user = User::find($userId); } if (!$userId) { header('HTTP/1.1 401 Unauthorized', true, 401); echo json_encode(array('error' => "Invalid parameters !")); return; } $this->view = null; $worklist_id = isset($_REQUEST['worklist_id']) ? $_REQUEST['worklist_id'] : $worklist_id; $notifyEmpty = true; $workitem = new WorkItem(); try { $workitem->loadById($worklist_id); } catch (Exception $e) { $error = $e->getMessage(); die($error); } if ($_SERVER['REQUEST_METHOD'] != 'POST') { if ($workitem->isInternal() && !$user->isInternal() || !$this->canEdit($workitem, $user)) { $this->write('msg', 'You don\'t have permissions to edit this job.'); $this->write('link', WORKLIST_URL); $this->view = new ErrorView(); parent::run(); exit; } $this->view = null; $this->write('jobId', $worklist_id); $this->write('user', $user); $this->write('workitem', $workitem); $this->view = new AddJobView(); parent::run(); return; } $journal_message = null; $status_change = ''; $status = $user->getIs_runner() ? $_REQUEST['status'] : 'Suggestion'; $fileUpload = isset($_REQUEST['fileUpload']) ? $_REQUEST['fileUpload'] : array(); $statusList = $this->getStatusList($workitem, $user); $args = array('summary', 'notes', 'status', 'project_id', 'sandbox', 'budget_id', 'assigned', 'is_internal', 'runner_id'); foreach ($args as $arg) { if (!empty($_REQUEST[$arg])) { ${$arg} = $_REQUEST[$arg]; } else { ${$arg} = ''; } } // code to add specifics to journal update messages $new_update_message = ''; $budget_id = !empty($_REQUEST['budget_id']) ? (int) $_REQUEST['budget_id'] : 0; $project_id = !empty($_REQUEST['project_id']) ? (int) $_REQUEST['project_id'] : 0; $runner_id = !empty($_REQUEST['runner_id']) ? (int) $_REQUEST['runner_id'] : 0; $sandbox = isset($_REQUEST['sandbox']) ? $_REQUEST['sandbox'] : ''; $old_budget_id = -1; if (isset($_REQUEST['budget_id']) && $workitem->getBudget_id() != $budget_id) { $new_update_message .= 'Budget changed. '; $old_budget_id = (int) $workitem->getBudget_id(); $workitem->setBudget_id($budget_id); $job_changes[] = '-budget'; } if (isset($_REQUEST['is_internal']) && $user->isInternal() && $workitem->isInternal() != (int) $_REQUEST['is_internal']) { $is_internal = !empty($_REQUEST['is_internal']) ? (int) $_REQUEST['is_internal'] : 0; $workitem->setIs_internal($is_internal); $workitem->save(); } // summary if (isset($_REQUEST['summary']) && $workitem->getSummary() != $_REQUEST['summary']) { $summary = $_REQUEST['summary']; $workitem->setSummary($summary); $new_update_message .= "Summary changed. "; if ($workitem->getStatus() != 'Draft') { $job_changes[] = '-summary'; } } if (isset($_REQUEST['labels']) && !empty($_REQUEST['labels'])) { $labelsArr = explode(',', $_REQUEST['labels']); // remove empty values foreach ($labelsArr as $key => $value) { $labelsArr[$key] = trim($value); if (empty($value)) { unset($labelsArr[$key]); } } // get current labels $labelsCur = $workitem->getWorkItemLabels(); // have labels been updated? $labelsDiff = array_diff($labelsArr, $labelsCur); if (is_array($labelsDiff) && !empty($labelsDiff)) { if ($workitem->getStatus() != 'Draft') { $new_update_message .= 'Labels updated: ' . implode(', ', $labelsArr); } // remove nasty end comma $new_update_message = rtrim($new_update_message, ', ') . '. '; $job_changes[] = '-labels'; } $workitem->setWorkitemLabels($labelsArr); $workitem->save(); } if ($workitem->getIsRelRunner() || $userId == $workitem->getRunnerId() || in_array($status, $statusList)) { if ($workitem->getStatus() != $status && !empty($status) && $status != 'Draft') { if ($this->changeStatus($workitem, $status, $user)) { if (!empty($new_update_message)) { // add commas where appropriate $new_update_message .= ", "; } $status_change = '-' . ucfirst(strtolower($status)); if ($status == 'Bidding' && Project::isAllowedRunnerForProject($user->getId(), $workitem->getProjectId())) { $workitem->setRunnerId($user->getId()); } $new_update_message .= "Status set to *{$status}*. "; } } } $related = ""; $notes = trim($_REQUEST['notes']); if (!empty($notes) && $workitem->getNotes() != $notes) { $workitem->setNotes($notes); $new_update_message .= "Notes changed. "; $job_changes[] = '-notes'; $related = $this->getRelated($notes); } // project if ($project_id && $workitem->getProjectId() != $project_id) { $workitem->setProjectId($project_id); if ($workitem->getStatus() != 'Draft') { $new_update_message .= "Project changed. "; $job_changes[] = '-project'; } } // Sandbox if (isset($_REQUEST['sandbox']) && $workitem->getSandbox() != $sandbox) { $workitem->setSandbox($sandbox); $new_update_message .= "Branch changed. "; $job_changes[] = '-branch'; } // Designer if (isset($_REQUEST['runner_id']) && $runner_id && $workitem->getRunnerId() != $runner_id) { $older_runner = $workitem->getRunner(); $workitem->setRunnerId($runner_id); $workitem->save(); if (!empty($older_runner)) { $runner = User::find($runner_id); $message = '\\#' . $workitem->getId() . ' updated by @' . $_SESSION['nickname'] . ' Designer reassigned to @' . $runner->getNickname(); Utils::systemNotification($message); $emails = !empty($older_runner) ? array($older_runner->getUsername()) : array(); array_push($emails, $runner->getUsername()); if ($workitem->getCreator()) { array_push($emails, $workitem->getCreator()->getUsername()); } if ($workitem->getMechanic()) { array_push($emails, $workitem->getMechanic()->getUsername()); } if ($user->getSelf_notif()) { array_push($emails, $user->getUsername()); } $options = array('type' => 'change-designer', 'workitem' => $workitem, 'emails' => $emails); $data = array('runner_nickname' => $runner->getNickname()); Notification::workitemNotify($options, $data); } } // Assignee $assigned = !empty($_REQUEST['assigned']) ? (int) $_REQUEST['assigned'] : 0; $assigneeChanged = false; if ($user->isInternal() && isset($_REQUEST['assigned']) && $workitem->getAssigned_id() != $assigned) { if ((int) $assigned == 0) { $workitem->setAssigned_id(0); $new_update_message .= "Assignee removed. "; $job_changes[] = '-assignee'; } else { $assignedUser = User::find($assigned); if ($assignedUser->isInternal()) { $assigneeChanged = true; $workitem->setAssigned_id($assignedUser->getId()); $currentStatus = $workitem->getStatus(); $new_update_message .= "Assignee changed. "; if ($currentStatus == 'Draft' || $currentStatus == 'Suggestion') { $workitem->setStatus('Bidding'); $new_update_message .= "Status set to *Bidding*. "; } $job_changes[] = '-assignee'; } } } if (empty($new_update_message)) { $new_update_message = " No changes."; } else { $workitem->save(); if ($old_budget_id > 0) { $budget = new Budget(); if ($budget->loadById($old_budget_id)) { $budget->recalculateBudgetRemaining(); } else { error_log("Old budget id not found: " . $old_budget_id); } if ($budget->loadById($workitem->getBudget_id())) { $budget->recalculateBudgetRemaining(); } else { error_log("New budget id not found: " . $workitem->getBudget_id()); } } $new_update_message = " Changes: {$new_update_message}"; $notifyEmpty = false; } if ($workitem->getStatus() != 'Draft' && !$notifyEmpty) { $journal_message .= '\\#' . $worklist_id . ' updated by @' . $_SESSION['nickname'] . $new_update_message . $related; $options = array('type' => 'workitem-update', 'workitem' => $workitem); $data = array('nick' => $_SESSION['nickname'], 'new_update_message' => $new_update_message, 'related' => $related); Notification::workitemNotify($options, $data, false); Notification::workitemNotifyHipchat($options, $data); Utils::systemNotification($journal_message); } if ($assigneeChanged) { $emailTemplate = 'job-assigned'; $data = array('job_id' => $workitem->getId(), 'summary' => $workitem->getSummary(), 'assigner' => $user->getNickname(), 'assigned' => $assignedUser->getNickname()); $senderEmail = 'Worklist - ' . $user->getNickname() . ' <*****@*****.**> '; Utils::sendTemplateEmail($assignedUser->getUsername(), $emailTemplate, $data, $senderEmail); } // if files were uploaded, update their workitem id $file = new File(); // update images first if (isset($fileUpload['uploads'])) { foreach ($fileUpload['uploads'] as $image) { $file->findFileById($image); $file->setWorkitem($workitem->getId()); $file->save(); } } if (!$notifyEmpty) { $options = array('type' => 'modified', 'workitem' => $workitem, 'status_change' => $status_change, 'job_changes' => $job_changes, 'recipients' => array('runner', 'creator', 'mechanic', 'followers')); $data = array('changes' => $new_update_message); Notification::workitemNotify($options, $data); } echo json_encode(array('return' => "Done!", 'workitem' => $workitem->getId(), 'success' => true)); }