require_once('code/tasks.php');
-function enc_money($float) {
- return format_money($float, $cents = true);
-}
-
function index_main() {
if(!logged_in()) {
return 'login';
$args = func_get_args();
$args = array_slice($args, 1);
array_unshift($args, 'tasks', 'id,price,title,state,client_id');
- print_r($args);
$rows = call_user_func_array('db_get_rows', $args);
#$rows = db_get_rows('tasks', 'id,price,title,state,client_id', $where_clause);
if($rows) {
function _index_main() {
$client_id = logged_in();
+
+ # make sure they've filled out the tiny user agreement
+ $tiny_agreement = db_get_value('people', 'tiny_agreement', 'where id=%i', $client_id);
+ if($tiny_agreement < 30) {
+ return './tiny_agreement';
+ }
+
if(logged_in_as_contractor()) {
- task_summary('needs_attention', 'where state=%i || state=%i || state=%i order by id desc', TASK_NEEDS_QUOTE, TASK_WORKING, TASK_BUG);
+ tem_show('needs_attention_header');
+ task_summary('needs_approval', 'where state=%i order by id desc', TASK_WORKING);
+ task_summary('needs_fixing', 'where state=%i || state=%i order by id desc', TASK_NEEDS_QUOTE, TASK_BUG);
task_summary('finished_unpaid', 'where state=%i && paid = 0 order by id desc', TASK_FINISHED);
task_summary('finished_paid', 'where state=%i && paid = 1 order by id desc', TASK_FINISHED);
+ task_summary('queue', 'where state=%i order by client_id, ord', TASK_QUEUED);
} else {
- task_summary('needs_attention', 'where state=' . TASK_DRAFT . ' || state=' . TASK_NEEDS_CLARIFICATION . ' || state=' . TASK_NEEDS_GO_AHEAD . ' || state=' . TASK_NEEDS_TESTING . ' order by id');
- task_summary('queue', 'where state=' . TASK_QUEUED . " && client_id=$client_id order by ord");
- task_summary('jason', 'where state=' . TASK_NEEDS_QUOTE . ' || state=' . TASK_WORKING . ' || state=' . TASK_BUG . ' order by id desc');
- #task_summary('jason_pricing', 'where state=' . TASK_NEEDS_QUOTE . ' order by id desc');
- #task_summary('jason_working', 'where state=' . TASK_WORKING . ' order by id desc');
- task_summary('finished_unpaid', 'where state=' . TASK_FINISHED . ' && paid = 0 order by id desc');
- task_summary('finished_paid', 'where state=' . TASK_FINISHED . ' && paid = 1 order by id desc');
+ if(db_count('tasks', 'where client_id=%i && (state=%i || state=%i || state=%i || state=%i)', $client_id, TASK_DRAFT, TASK_NEEDS_CLARIFICATION, TASK_NEEDS_GO_AHEAD, TASK_NEEDS_TESTING)) {
+ tem_show('needs_attention_header');
+ task_summary('needs_approval', 'where client_id=%i && (state=%i || state=%i) order by id', $client_id, TASK_NEEDS_GO_AHEAD, TASK_NEEDS_TESTING);
+ task_summary('needs_fixing', 'where client_id=%i && (state=%i || state=%i) order by id', $client_id, TASK_DRAFT, TASK_NEEDS_CLARIFICATION);
+ }
+ task_summary('queue', 'where client_id=%i && state=%i order by ord', $client_id, TASK_QUEUED);
+ task_summary('jason', 'where client_id=%i && (state=%i || state=%i) order by id desc', $client_id, TASK_NEEDS_QUOTE, TASK_BUG);
+ task_summary('jason_working', 'where client_id=%i && state=%i order by id desc', $client_id, TASK_WORKING);
+ task_summary('finished_unpaid', 'where client_id=%i && state=%i && paid=0 order by id desc', $client_id, TASK_FINISHED);
+ task_summary('finished_paid', 'where client_id=%i && state=%i && paid=1 order by id desc', $client_id, TASK_FINISHED);
}
return;
}
<!--~display_body start~-->
<h3><!--~normal_title start~-->Task #~task_id~<!--~end~--><!--~bug_title start~-->Problem Report<!--~end~--> "~title.html~"</h3>
+
<p><strong>Title</strong>: ~title.html~</p>
<p><strong>Status</strong>: ~state.html~</p>
<p style="padding-left: 20px; text-indent: -20px"><strong>Narrative</strong>:<br />
~description.htmlbrtab~</p>
+ <!--~price_row start~--><p><strong>Price</strong>: ~price.money~</p><!--~end~-->
+
+ <!--~approve_price_link start~--><p><a href="tasks?tasks_approve_price_id=~task_id.attr~">Approve price</a></p><!--~end~-->
+
+ <!--~normal_edit_link start~--><p><a href="tasks?tasks_edit_id=~task_id.attr~">Edit this task</a></p><!--~end~-->
+ <!--~warning_edit_link start~--><p><a href="tasks?tasks_edit_id=~task_id.attr~" onclick="return confirm('Editing this task will invalidate the price, proceed anyway?')">Edit this task</a></p><!--~end~-->
+
+ <!--~working_link start~--><p><a href="tasks?tasks_working_id=~task_id.attr~">I'm starting on this now</a>.</p><!--~end~-->
+
+ <!--~needs_testing_link start~--><p><a href="tasks?tasks_needs_testing_id=~task_id.attr~">Mark this task as finished (request testing)</a>.</p><!--~end~-->
+
+ <!--~finished_link start~--><p>Please test everything in the narrative! If everything is working, <a href="tasks?tasks_finished_id=~task_id.attr~">Mark this task as finished</a> Otherwise please e-mail or call Jason.</p><!--~end~-->
+
<p><a href="./">Back</a></p>
<!--~end~-->
<tr><td class="caption">URL: </td><td class="field"><input type="text" size="40" name="url" value="~url.attr~" /></td></tr>
- <tr><td colspan="2"><!--~normal_instructions start~-->Below, write as if the change/addition you would like has already been implemented. Write a first-person narrative with the specifics of what you do and what you see as a result. <a target="_new" href="narrative_example">See an example</a>.<!--~end~--><!--~bug_instructions start~-->Below, describe in detail 1) what you do, 2) what you expect to see, 3) what you see instead<!--~end~--></td></tr>
+ <tr><td colspan="2">
+ <!--~fixme_instructions start~-->The narrative below contains "FIXME". This is Jason's way of marking the places in the narrative that need your attention. Please update these parts of the narrative to be more complete/specific and remove the "FIXME".<!--~end~-->
+ <!--~set_price_instructions start~-->Mark trouble spots with "FIXME".<!--~end~-->
+ <!--~normal_instructions start~-->Below, write as if the change/addition you would like has already been implemented. Write a first-person narrative with the specifics of what you do and what you see as a result. <a target="_new" href="narrative_example">See an example</a>.<!--~end~-->
+ <!--~bug_instructions start~-->Below, describe in detail 1) what you do, 2) what you expect to see, 3) what you see instead<!--~end~-->
+ </td></tr>
<tr><td colspan="2" class="field"><textarea rows="20" cols="50" name="description">~description.html~</textarea></td></tr>
+<!--~price_field start~-->
+ <tr><td class="caption">Price: </td><td class="field"><input type="text" size="10" name="price" value="~price.attr~" /></td></tr>
+<!--~end~-->
+<!--~contractor_submits start~-->
+ <tr><td class="submit_row" colspan="2"><input type="submit" name="save_price" value="Save With Price" /></td></tr>
+ <tr><td class="submit_row" colspan="2"><input type="submit" name="save_draft" value="Save As Draft" /></td></tr>
+ <tr><td class="submit_row" colspan="2"><input type="submit" name="needs_clarification" value="Needs Clarification" /></td></tr>
+<!--~end~-->
<!--~normal_submits start~-->
- <tr><td class="submit_row" colspan="2"><input type="submit" name="save" value="Save and Request Price" /></td></tr>
+ <tr><td class="submit_row" colspan="2"><input type="submit" name="request_price" value="Save and Request Price" /></td></tr>
<tr><td class="submit_row" colspan="2"><input type="submit" name="save_draft" value="Save Draft" /></td></tr>
<!--~end~-->
<!--~bug_submit start~-->
$GLOBALS['tasks_form_recipient'] = "fixme@example.com";
-define('TASKS_DB_FIELDS', 'title,url,description,state');
require_once('code/wfpl/template.php');
require_once('code/wfpl/email.php');
require_once('code/db_connect.php');
+function description_has_fixmes($description) {
+ return (strpos($description, 'FIXME') !== false);
+}
+
# replace every character in $str with " "
function tonbsp($matches) {
return str_repeat(' ', strlen($matches[0]) * 2);
$title = format_oneline($_REQUEST['title']);
$url = format_oneline($_REQUEST['url']);
$description = format_unix($_REQUEST['description']);
+ $price = format_decimal($_REQUEST['price']);
- tasks_tem_sets($title, $url, $description);
+ tasks_tem_sets($title, $url, $description, $price);
- return array($title, $url, $description);
+ return array($title, $url, $description, $price);
}
-function tasks_tem_sets($title, $url, $description) {
+function tasks_tem_sets($title, $url, $description, $price) {
tem_set('title', $title);
tem_set('url', $url);
tem_set('description', $description);
+ tem_set('price', $price);
}
function tasks_main() {
function tasks_display_main() {
$task_id = format_int($_REQUEST['tasks_id']);;
- $row = db_get_row('tasks', 'title,url,description,state', 'where id=%i', $task_id);
+ $client_id = logged_in();
+ if(logged_in_as_contractor()) {
+ $row = db_get_row('tasks', 'title,url,description,state,price', 'where id=%i', $task_id);
+ } else {
+ $row = db_get_row('tasks', 'title,url,description,state,price', 'where id=%i && client_id=%i', $task_id, $client_id);
+ }
if($row) {
- list($title, $url, $description, $state) = $row;
+ list($title, $url, $description, $state, $price) = $row;
tem_set('task_id', $task_id);
tem_set('title', $title);
tem_set('url', $url);
tem_set('description', $description);
tem_set('state', task_state_pretty($state));
+ tem_set('price', $price);
if($state == TASK_BUG) {
tem_show('bug_title');
} else {
tem_show('normal_title');
}
+ if(logged_in_as_contractor()) {
+ switch($state) {
+ case TASK_DRAFT:
+ case TASK_NEEDS_CLARIFICATION:
+ case TASK_NEEDS_QUOTE:
+ case TASK_BUG:
+ case TASK_NEEDS_GO_AHEAD:
+ tem_show('normal_edit_link');
+ tem_show('price_row');
+ break;
+ case TASK_QUEUED:
+ tem_show('normal_edit_link');
+ tem_show('working_link');
+ tem_show('price_row');
+ case TASK_WORKING:
+ tem_show('price_row');
+ tem_show('needs_testing_link');
+ break;
+ case TASK_NEEDS_TESTING:
+ case TASK_FINISHED:
+ tem_show('price_row');
+ break;
+ }
+ } else {
+ switch($state) {
+ case TASK_DRAFT:
+ case TASK_NEEDS_CLARIFICATION:
+ case TASK_NEEDS_QUOTE:
+ case TASK_BUG:
+ tem_show('normal_edit_link');
+ break;
+ case TASK_NEEDS_GO_AHEAD:
+ tem_show('price_row');
+ tem_show('approve_price_link');
+ tem_show('warning_edit_link');
+ break;
+ case TASK_QUEUED:
+ tem_show('price_row');
+ tem_show('warning_edit_link');
+ break;
+ case TASK_WORKING:
+ tem_show('price_row');
+ break;
+ case TASK_NEEDS_TESTING:
+ tem_show('price_row');
+ tem_show('finished_link');
+ break;
+ case TASK_FINISHED:
+ tem_show('price_row');
+ break;
+ }
+ }
} else {
message("Task #$task_id not found");
return './';
function tasks_edit_main() {
$state = TASK_DRAFT; # will be overwritten
+ $client_id = logged_in(); # fixed shortly if we're contractor
$edit_id = format_int($_REQUEST['tasks_edit_id']);
unset($_REQUEST['tasks_edit_id']);
if($edit_id) {
+ $owner = db_get_value('tasks', 'client_id', 'where id=%i', $edit_id);
+ if(logged_in_as_contractor()) {
+ $client_id = $owner;
+ } elseif($owner != $client_id) {
+ message('Sorry, that task was entered by/for another client.');
+ return './';
+ }
+
# add hidden field for database id of row we're editing
tem_set('tasks_edit_id', $edit_id);
tem_show('editing');
}
if(isset($_REQUEST['tasks_new_bug'])) {
- tem_show('bug_submit');
$state = TASK_BUG;
- } else {
- tem_show('normal_submits');
}
- if($state == TASK_BUG) {
- tem_show('bug_instructions');
- } else {
- tem_show('normal_instructions');
+ if(isset($_REQUEST['tasks_approve_price_id'])) {
+ $id = $_REQUEST['tasks_approve_price_id'];
+ $owner = db_get_value('tasks', 'client_id', 'where id=%i', $id);;
+ if(logged_in() != $owner) {
+ message("Error: can't approve a task entered by/for another client.");
+ return './';
+ }
+ db_update('tasks', 'state', TASK_QUEUED, 'where id=%i', $id);
+ message('Price approved.');
+ return './';
+ }
+
+ if(isset($_REQUEST['tasks_working_id'])) {
+ $id = $_REQUEST['tasks_working_id'];
+ if(!logged_in_as_contractor()) {
+ message("Error: only Jason can say what he's working on.");
+ return './';
+ }
+ db_update('tasks', 'state', TASK_WORKING, 'where id=%i', $id);
+ message('OK, client locked out of modifying that one.');
+ return './';
+ }
+
+ if(isset($_REQUEST['tasks_needs_testing_id'])) {
+ $id = $_REQUEST['tasks_needs_testing_id'];
+ if(!logged_in_as_contractor()) {
+ message("Error: only Jason can say when he's done.");
+ return './';
+ }
+ db_update('tasks', 'state', TASK_NEEDS_TESTING, 'where id=%i', $id);
+ message('Task awaits testing.');
+ return './';
+ }
+
+ if(isset($_REQUEST['tasks_finished_id'])) {
+ $id = $_REQUEST['tasks_finished_id'];
+ $owner = db_get_value('tasks', 'client_id', 'where id=%i', $id);;
+ if(logged_in() != $owner) {
+ message("Error: can't test a task entered by/for another client.");
+ return './';
+ }
+ db_update('tasks', 'state', TASK_FINISHED, 'where id=%i', $id);
+ message('Task marked as finished.');
+ # FIXME also mark it as paid if client's balance can cover it
+ return './';
}
$delete_id = format_int($_REQUEST['tasks_delete_id']);
}
if(isset($_REQUEST['title'])) {
- list($title, $url, $description) = tasks_get_fields();
+ list($title, $url, $description, $price) = tasks_get_fields();
# FIXME
if(isset($_REQUEST['save_draft'])) {
$state = TASK_DRAFT;
} elseif(isset($_REQUEST['save_bug'])) {
$state = TASK_BUG;
- } else {
- $state = TASK_NEEDS_QUOTE;
+ } elseif(isset($_REQUEST['save_price']) && logged_in_as_contractor()) {
+ $tiny_agreement = db_get_value('people', 'tiny_agreement', 'where id=%i', $client_id);
+ if($price < $tiny_agreement) {
+ $state = TASK_QUEUED;
+ } else {
+ $state = TASK_NEEDS_GO_AHEAD;
+ }
+ } elseif(isset($_REQUEST['needs_clarification'])) {
+ $state = TASK_NEEDS_CLARIFICATION;
+ } else { # better be "request_price"
+ if(description_has_fixmes($description)) {
+ $state = TASK_NEEDS_CLARIFICATION;
+ message('The description is not ready to be priced yet because it still contains at least one "FIXME".');
+ } else {
+ $state = TASK_NEEDS_QUOTE;
+ }
}
if("you're happy with the POSTed values") {
if($edit_id) {
- db_update('tasks', 'title,url,description,state', $title, $url, $description, $state, 'where id=%i', $edit_id);
+ if(isset($_REQUEST['price']) && logged_in_as_contractor()) {
+ db_update('tasks', 'title,url,description,state,price', $title, $url, $description, $state, $price, 'where id=%i', $edit_id);
+ } else {
+ db_update('tasks', 'title,url,description,state', $title, $url, $description, $state, 'where id=%i', $edit_id);
+ }
message('Task updated.');
} else {
# new task
$paid = 0;
- $client_id = 4; # FIXME
+ $client_id = logged_in();
db_insert('tasks', 'client_id,title,url,description,state,paid', $client_id, $title, $url, $description, $state, $paid);
message('Task saved.');
}
# fix their entry in whatever way you require.
} elseif($edit_id) {
# we've recieved an edit id, but no data. So we grab the values to be edited from the database
- list($client_id, $ord, $title, $url, $description, $state, $paid) = db_get_row('tasks', TASKS_DB_FIELDS, 'where id=%i', $edit_id);
- tasks_tem_sets($client_id, $ord, $title, $url, $description, $state, $paid);
+ list($title, $url, $description, $state, $paid) = db_get_row('tasks', 'title,url,description,state,price', 'where id=%i', $edit_id);
+ tasks_tem_sets($title, $url, $description, $price);
} else {
# form not submitted, you can set default values like so:
#tem_set('client_id', 'Yes');
}
- # this has to be later in the file because it requres that client_id be set already
+ # display header
if($edit_id) {
tem_show('edit_msg');
} elseif($state == TASK_BUG) {
} else {
tem_show('new_msg');
}
+
+ # display instructions
+ if($state == TASK_BUG) {
+ tem_show('bug_instructions');
+ if(logged_in_as_contractor()) {
+ tem_show('price_field');
+ tem_show('contractor_submits');
+ } else {
+ tem_show('bug_submit');
+ }
+ } elseif($state == TASK_NEEDS_QUOTE && logged_in_as_contractor()) {
+ tem_show('set_price_instructions');
+ tem_show('price_field');
+ tem_show('contractor_submits');
+ } else {
+ if(description_has_fixmes($description)) {
+ tem_show('fixme_instructions');
+ } else {
+ tem_show('normal_instructions');
+ }
+ tem_show('normal_submits');
+ }
}
?>