diff --git a/admin/report/fitandproper/cpdactivityadmin.php b/admin/report/fitandproper/cpdactivityadmin.php
new file mode 100644
index 00000000000..f7ff94d35a6
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivityadmin.php
@@ -0,0 +1,437 @@
+libdir.'/adminlib.php');
+require_once('cpdactivityadmin_edit_form.php');
+require_once('cpdactivityadmin_links_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewcpdactivities', get_context_instance(CONTEXT_SYSTEM));
+
+$filter_code = optional_param('filter_code', null,PARAM_INTEGER);
+$filter_name = optional_param('filter_name', null,PARAM_INTEGER);
+$filter_type = optional_param('filter_type', null,PARAM_INTEGER);
+$filter_code_text = optional_param('filter_code_text', null,PARAM_TEXT);
+$filter_name_text = optional_param('filter_name_text', null,PARAM_TEXT);
+$filter_type_text = optional_param('filter_type_text', null,PARAM_TEXT);
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+$step = optional_param('step', null,PARAM_INTEGER);
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivityadmin.php";
+
+/*
+ * Check if there is Activity types in db, else create them
+ */
+$type_count = $DB->count_records('cpd_activity_type');
+if($type_count == 0)
+{
+ $atype = new stdClass();
+ $atype->name = 'Seminar';
+ $DB->insert_record('cpd_activity_type',$atype,false);
+ $atype->name = 'Workshop';
+ $DB->insert_record('cpd_activity_type',$atype,false);
+ $atype->name = 'Industry Course';
+ $DB->insert_record('cpd_activity_type',$atype,false);
+ $atype->name = 'Conference';
+ $DB->insert_record('cpd_activity_type',$atype,false);
+ $atype->name = 'Other';
+ $DB->insert_record('cpd_activity_type',$atype,false);
+}
+
+// Print the header.
+admin_externalpage_setup('cpdactivityadmin');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('cpdactivityadmin_heading', 'report_fitandproper'));
+
+/*
+ * Check if user requested an add or edit activity
+ */
+$display = true;
+if($op == 'add' || $op == 'edit')
+{
+ // Include the required JavaScript.
+ $jsmodule = array(
+ 'name' => 'report_fitandproper',
+ 'fullpath' => '/admin/report/fitandproper/module.js',
+ 'requires' => array("overlay", "anim", "plugin")); //on this line you are loading three other YUI modules
+ $PAGE->requires->js_init_call('M.report_fitandproper.init',null,false,$jsmodule);
+
+ $edit_form = new cpdactivityadmin_edit_form(null,array('op'=>$op,'id'=>$id));
+ $data = $edit_form->get_data();
+
+ if($edit_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($data || $step == 2)
+ {
+ /*
+ * Check if user is doing an edit and display the links report
+ */
+ if($op == 'edit')
+ {
+ $links_form = new cpdactivityadmin_links_form(null,array('edit_form'=>$data));
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($ldata = $links_form->get_data())
+ {
+ //edit
+ //create institution object
+ $record = new stdClass();
+ if($ldata->id != null && $ldata->id > 0)
+ {
+ $record->id = $ldata->id;
+ }
+ $record->cpd_activity_type_id = $ldata->type;
+ $record->name = $ldata->name;
+ $record->code = $ldata->code;
+ $record->hours = $ldata->hours;
+ $record->enabled = (isset($ldata->enabled)) ? (int)$ldata->enabled : 0;
+ $record->timemodified = time();
+ $DB->update_record('cpd_activity', $record, false, false);
+
+ //insert categories
+ $DB->delete_records('cpd_activity_fais_sub_cat',array('cpd_activity_id'=>$record->id));
+
+ if(isset($_POST['subcategory']))
+ {
+ foreach($_POST['subcategory'] as $catid)
+ {
+ $cat_record = new stdClass();
+ $cat_record->cpd_activity_id = $record->id;
+ $cat_record->fais_sub_category_id = $catid;
+ $DB->insert_record('cpd_activity_fais_sub_cat', $cat_record, false, false);
+ }
+ }
+
+ // Log.
+ add_to_log(SITEID, 'CPD Activity', ": Edit", "report/fitandproper/cpdactivityadmin.php",$record->name);
+ redirect($url);
+ }else
+ {
+ display_cpdactivity_links($data->id);
+
+ $links_form->display();
+ }
+ }
+
+ /*
+ * Add a new institution to the database
+ */
+ if($op == 'add')
+ {
+ //save
+ //create activity object
+ $record = new stdClass();
+ if($data->id != null && $data->id > 0)
+ {
+ $record->id = $data->id;
+ }
+ $record->cpd_activity_type_id = $data->type;
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->hours = $data->hours;
+ $record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->timecreated = time();
+ $ins_id = $DB->insert_record('cpd_activity', $record, true, false);
+
+ //insert categories
+ if(isset($_POST['subcategory']))
+ {
+ foreach($_POST['subcategory'] as $catid)
+ {
+ $cat_record = new stdClass();
+ $cat_record->cpd_activity_id = $ins_id;
+ $cat_record->fais_sub_category_id = $catid;
+ $DB->insert_record('cpd_activity_fais_sub_cat', $cat_record, false, false);
+ }
+ }
+
+ // Log.
+ add_to_log(SITEID, 'CPD Activity', ": Add", "report/fitandproper/cpdactivityadmin.php",$record->name);
+
+ redirect($url);
+ }
+ }else
+ {
+ $edit_form->display();
+ }
+ $display = false;
+}
+elseif($op == 'delete')
+{
+ /*
+ * Handle the deletion of CPD Activities
+ */
+ require_capability('report/fitandproper:deletecpdactivities', get_context_instance(CONTEXT_SYSTEM));
+
+ $data = $DB->get_record('cpd_activity',array('id'=>$id,'deleted'=>0));
+ $data->type = 0;
+
+ $data->op = 'delete';
+ $links_form = new cpdactivityadmin_links_form(null,array('edit_form'=>$data));
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($ldata = $links_form->get_data())
+ {
+ /*
+ * Do the deletion
+ */
+ $DB->set_field('user_cpd_activity', 'deleted', 1, array('cpd_activity_id'=>$ldata->id));
+
+ $record = new stdClass();
+ $record->id = $ldata->id;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('cpd_activity', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'CPD Activity', ": Delete", "report/fitandproper/cpdactivityadmin.php",$data->name);
+
+ redirect($url);
+ }else
+ {
+ display_cpdactivity_links($data->id);
+ $links_form->display();
+ }
+ $display = false;
+}
+//echo $OUTPUT->notification('test');
+
+if($display)
+{
+ /*
+ * Display filter
+ */
+
+ $filteroptions = array(
+ 1=>'contains',
+ 2=>'doesn\'t contain',
+ 3=>'is equal to',
+ 4=>'starts with',
+ 5=>'ends with',
+ 6=>'is empty');
+ echo $OUTPUT->box_start('filterlist');
+ echo '
';
+ echo ''.get_string('cpdactivityadmin_filterhead', 'report_fitandproper').' ';
+ echo '';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+ /*
+ * Get list of institutions from database and apply filters if neccesary
+ */
+ if($filter_code_text != null || $filter_name_text != null || $filter_code == 6 || $filter_name == 6 || $filter_type_text != null || $filter_type == 6)
+ {
+ $where= '';
+ $params = array();
+ if($filter_type_text != null || $filter_type == 6)
+ {
+ $tparams = array();
+ switch($filter_type)
+ {
+ case 1 : $twhere = 'name LIKE ?';
+ $tparams[] = '%'.$filter_type_text.'%';
+ break;
+ case 2 : $twhere = 'name NOT LIKE ?';
+ $tparams[] = '%'.$filter_code_text.'%';
+ break;
+ case 3 : $twhere = 'name = ?';
+ $tparams[] = $filter_code_text;
+ break;
+ case 4 : $twhere = 'name LIKE ?';
+ $tparams[] = $filter_code_text.'%';
+ break;
+ case 5 : $twhere = 'name LIKE ?';
+ $tparams[] = '%'.$filter_code_text;
+ break;
+ case 6 : $twhere = 'name IS NULL OR name = ""';
+ break;
+ }
+ $a_types = $DB->get_records_select('cpd_activity_type',$twhere,$tparams,'name');
+ $tids = '';
+ if(count($a_types) > 0)
+ {
+ foreach($a_types as $t)
+ {
+ $tids .= "{$t->id},";
+ }
+ }else
+ {
+ $tids = '0';
+ }
+ $tids = rtrim($tids,',');
+ $where = "cpd_activity_type_id in ($tids)";
+ }
+ if($filter_code_text != null || $filter_code == 6)
+ {
+ if($filter_code_text != null) $where .= ' AND ';
+ switch($filter_code)
+ {
+ case 1 : $where .= 'code LIKE ?';
+ $params[] = '%'.$filter_code_text.'%';
+ break;
+ case 2 : $where .= 'code NOT LIKE ?';
+ $params[] = '%'.$filter_code_text.'%';
+ break;
+ case 3 : $where .= 'code = ?';
+ $params[] = $filter_code_text;
+ break;
+ case 4 : $where .= 'code LIKE ?';
+ $params[] = $filter_code_text.'%';
+ break;
+ case 5 : $where .= 'code LIKE ?';
+ $params[] = '%'.$filter_code_text;
+ break;
+ case 6 : $where .= 'code IS NULL OR code = ""';
+ break;
+ }
+ }
+ if($filter_name_text != null || $filter_name == 6)
+ {
+ if($filter_code_text != null) $where .= ' AND ';
+ switch($filter_name)
+ {
+ case 1 : $where .= 'name LIKE ?';
+ $params[] = '%'.$filter_name_text.'%';
+ break;
+ case 2 : $where .= 'name NOT LIKE ?';
+ $params[] = '%'.$filter_name_text.'%';
+ break;
+ case 3 : $where .= 'name = ?';
+ $params[] = $filter_name_text;
+ break;
+ case 4 : $where .= 'name LIKE ?';
+ $params[] = $filter_name_text.'%';
+ break;
+ case 5 : $where .= 'name LIKE ?';
+ $params[] = '%'.$filter_name_text;
+ break;
+ case 6 : $where .= 'name IS NULL OR code = ""';
+ break;
+ }
+ }
+ $where .= ' AND deleted = 0';
+
+ $activities = $DB->get_records_select('cpd_activity',$where,$params,'name');
+ }
+ else
+ {
+ //no filter selected so get all records
+ $activities = $DB->get_records('cpd_activity',array('deleted'=>0),'name');
+ }
+
+ /*
+ * Display intitions list table
+ */
+ echo $OUTPUT->box_start('cpdactivitylist');
+ echo ''.get_string('cpdactivityadmin_addnew', 'report_fitandproper').'
';
+
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('cpdactivityadmin_tableheadtype', 'report_fitandproper'),get_string('cpdactivityadmin_tableheadcode', 'report_fitandproper'),get_string('cpdactivityadmin_tableheadname', 'report_fitandproper'),'','');
+
+ $r = array();
+
+ if(count($activities) > 0)
+ {
+ foreach($activities as $a)
+ {
+ $type = $DB->get_record('cpd_activity_type',array('id'=>$a->cpd_activity_type_id));
+ $edit = html_writer::link($url.'?op=edit&id='.$a->id,get_string('cpdactivityadmin_tableedit', 'report_fitandproper'));
+ $delete = html_writer::link($url.'?op=delete&id='.$a->id,get_string('cpdactivityadmin_tabledelete', 'report_fitandproper'));
+ $row = new html_table_row(array($type->name,$a->code,$a->name,$edit,$delete));
+ if($a->enabled == 0) $row->attributes = array('class'=>'faiscategorydisabled');
+ $table->data[] = $row;
+ //$table->data[] = array($i->code,$i->name,$edit,$delete);
+ }
+ }
+ else
+ {
+ $empty = new html_table_cell(get_string('cpdactivityadmin_tablenorows', 'report_fitandproper'));
+ $empty->colspan = '5';
+ $row = new html_table_row(array($empty));
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+
+ echo ''.get_string('cpdactivityadmin_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+// Footer.
+echo $OUTPUT->footer();
+
+/**
+ * Function to display a report of all the users linked to an activity
+ * @param integer ID of the activity being edited or deleted
+ */
+function display_cpdactivity_links($activity_id)
+{
+ global $DB;
+
+ $activity = $DB->get_record('cpd_activity',array('id'=>$activity_id));
+
+ /*
+ * Get all cpd activities
+ */
+ $activities = $DB->get_records_sql('SELECT moodle_user_id,timecreated FROM {user_cpd_activity} WHERE cpd_activity_id = ? AND deleted = 0',array($activity_id));
+
+ /*
+ * Put all the qualifications and activities in one array for processing
+ */
+ $links = array();
+
+ foreach($activities as $a)
+ {
+ $links[$a->moodle_user_id] = date('Y-m-d',$a->timecreated);
+ }
+
+ /*
+ * Display the table
+ */
+ echo ''.get_string('cpdactivityadmin_report_heading', 'report_fitandproper').' '.$activity->name.' ';
+ $table = new html_table();
+ //$table->attributes = array('class'=>'center');
+ $table->head = array(get_string('cpdactivityadmin_report_user_title', 'report_fitandproper'),get_string('cpdactivityadmin_report_time_title', 'report_fitandproper'));
+
+ if($links)
+ {
+ foreach($links as $user=>$l)
+ {
+ //get user name
+ $username = $DB->get_record('user',array('id'=>$user),'firstname,lastname');
+ $row = array($username->firstname.' '.$username->lastname,$l);
+ $table->data[] = $row;
+ }
+ }else
+ {
+ $row = array(get_string('cpdactivityadmin_report_no_users', 'report_fitandproper'));
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivityadmin_ajax.php b/admin/report/fitandproper/cpdactivityadmin_ajax.php
new file mode 100644
index 00000000000..96dc33a64ea
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivityadmin_ajax.php
@@ -0,0 +1,32 @@
+libdir.'/adminlib.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewcpdactivities', get_context_instance(CONTEXT_SYSTEM));
+
+$cid = (int)$_GET['cid'];
+
+if($cid > 0)
+{
+ $categories = $DB->get_records('fais_sub_category',array('fais_category_id'=>$cid,'enabled'=>1,'deleted'=>0),'name','id,name');
+ $count = count($categories);
+ if($count > 0)
+ {
+ $return = array('categories'=>$categories,'count'=>$count);
+ print json_encode($return);
+ }else
+ {
+ print json_encode(array('count'=>0));
+ }
+}
+?>
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivityadmin_edit_form.php b/admin/report/fitandproper/cpdactivityadmin_edit_form.php
new file mode 100644
index 00000000000..82774a134a1
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivityadmin_edit_form.php
@@ -0,0 +1,144 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the CPD Activities add/edit form
+ */
+class cpdactivityadmin_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+
+ /*
+ * if this is a edit form get the activity data for edit
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $data = $DB->get_record('cpd_activity',array('id'=>$id,'deleted'=>0));
+ }
+
+ /*
+ * get activity types
+ */
+ $dtypes = $DB->get_records('cpd_activity_type');
+ $types = array();
+ foreach($dtypes as $t)
+ {
+ $types[$t->id] = $t->name;
+ }
+
+ /*
+ * get list of top level categories
+ */
+ $fais_categories = $DB->get_records('fais_category',array('deleted'=>0,'enabled'=>1),'name','id,name');
+ $category_list = array('0'=>'Please select ...');
+ foreach($fais_categories as $category)
+ {
+ $category_list[$category->id] = $category->name;
+ }
+
+ $fais_sub_categories = array(0=>'Please select a category');
+ if($op == 'edit')
+ {
+ $mform->setDefault('id', $id);
+ $mform->setDefault('name', $data->name);
+ $mform->setDefault('code', $data->code);
+ $mform->setDefault('hours', $data->hours);
+ $mform->setDefault('enabled', $data->enabled);
+ $mform->setDefault('type', $data->cpd_activity_type_id);
+
+ //get and set categories
+ $sub_categories = $DB->get_records_sql('SELECT * FROM {cpd_activity_fais_sub_cat} scl INNER JOIN mdl_fais_sub_category sc ON (scl.fais_sub_category_id = sc.id) WHERE scl.cpd_activity_id = ? ORDER BY sc.name',array($id));
+ $top = 0;
+ $fais_sub_categories = array();
+ $sub_categories_defaults = array();
+ foreach($sub_categories as $sc)
+ {
+ $top = $sc->fais_category_id;
+ $sub_categories_defaults[] = $sc->fais_sub_category_id;
+ }
+
+ //get all sub categories
+ $sub_categories = $DB->get_records('fais_sub_category',array('fais_category_id'=>$top,'enabled'=>1,'deleted'=>0),'name','id,name');
+ foreach($sub_categories as $sc)
+ {
+ $fais_sub_categories[$sc->id] = $sc->name;
+ }
+
+ $mform->setDefault('subcategory', $sub_categories_defaults);
+ $mform->setDefault('category', $top);
+
+ }else
+ {
+ $mform->setDefault('enabled', 1);
+ }
+
+ $header = ($op == 'edit') ? 'Edit' : 'Add';
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('select', 'type', get_string('cpdactivity_type', 'report_fitandproper'), $types);
+ $mform->addElement('text', 'code', get_string('cpdactivity_code', 'report_fitandproper'));
+ $mform->addRule('code', null, 'required', null, 'client');
+ $mform->addRule('code', null, 'maxlength', 255, 'client');
+ $mform->addRule('code', get_string('cpdactivity_codeformat', 'report_fitandproper'), 'regex', "/^[a-zA-Z0-9_]+$/", 'client');
+
+ $mform->addElement('text', 'name', get_string('cpdactivity_name', 'report_fitandproper'));
+ $mform->addRule('name', null, 'required', null, 'client');
+ $mform->addRule('name', null, 'maxlength', 255, 'client');
+ $mform->addRule('name', get_string('cpdactivity_nameformat', 'report_fitandproper'), 'regex', "/^[a-zA-Z0-9\s]+$/", 'client');
+ $mform->addElement('text', 'hours', get_string('cpdactivity_hours', 'report_fitandproper'));
+ $mform->addRule('hours', null, 'numeric', null, 'client');
+ $mform->addElement('select', 'category', get_string('cpdactivity_category', 'report_fitandproper'), $category_list);
+
+ $subselect = $mform->addElement('select', 'subcategory', get_string('cpdactivity_subcategory', 'report_fitandproper'), $fais_sub_categories);
+ $subselect->setMultiple(true);
+ $mform->disabledIf('subcategory', 'category', 'eq', 0);
+
+ $mform->addElement('checkbox', 'enabled', get_string('enabled', 'report_fitandproper'));
+
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'id');
+
+ $this->add_action_buttons(true,get_string('cpdactivity_submit', 'report_fitandproper'));
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+ //check for duplicate code
+ $check = $DB->count_records_select('cpd_activity','deleted = 0 and code = ? and id != ?',array($data['code'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['code'] = get_string('cpdactivity_submit_duplicate_code', 'report_fitandproper');
+ }
+
+ //check for duplicate name
+ $check = $DB->count_records_select('cpd_activity','deleted = 0 and name = ? and id != ?',array($data['name'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['name'] = get_string('cpdactivity_submit_duplicate_name', 'report_fitandproper');
+ }
+
+ //check that a sub category is selected when top category is selected
+ if($data['category'] > 0)
+ {
+ if(!isset($_POST['subcategory']) || $_POST['subcategory'][0] == '0')
+ {
+ $errors['subcategory'] = get_string('cpdactivity_submit_nosub', 'report_fitandproper');
+ }
+ }
+
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivityadmin_links_form.php b/admin/report/fitandproper/cpdactivityadmin_links_form.php
new file mode 100644
index 00000000000..db771b88bb1
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivityadmin_links_form.php
@@ -0,0 +1,49 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the CPD Activities edit links report form
+ */
+class cpdactivityadmin_links_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $edit_form = $this->_customdata['edit_form'];
+ //$can_save = $this->_customdata['can_save'];
+
+ $mform->addElement('hidden', 'id', $edit_form->id);
+ $mform->addElement('hidden', 'name', $edit_form->name);
+ $mform->addElement('hidden', 'code', $edit_form->code);
+ $mform->addElement('hidden', 'type', $edit_form->type);
+ $mform->addElement('hidden', 'hours', $edit_form->hours);
+ $mform->addElement('hidden', 'enabled', $edit_form->enabled);
+ $mform->addElement('hidden', 'op', $edit_form->op);
+ $mform->addElement('hidden', 'step', 2);
+
+ //use POST because Moodle does not like a selectbox that was filled by ajax
+ if($edit_form->op != 'delete')
+ {
+ if($_POST['subcategory'])
+ {
+ foreach($_POST['subcategory'] as $sc)
+ {
+ $mform->addElement('hidden', 'subcategory[]', $sc);
+ }
+ }
+ }
+
+ if($edit_form->op == 'edit')
+ {
+ $this->add_action_buttons(true,get_string('cpdactivityadmin_report_submit', 'report_fitandproper'));
+ }else
+ {
+ $this->add_action_buttons(true,get_string('cpdactivityadmin_report_submit_delete', 'report_fitandproper'));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivitymaintenance.php b/admin/report/fitandproper/cpdactivitymaintenance.php
new file mode 100644
index 00000000000..5721d757eb0
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivitymaintenance.php
@@ -0,0 +1,182 @@
+id === 0) {
+ $SESSION->wantsurl = $CFG->wwwroot . '/admin/report/fitandproper/cpdactivitymaintenance.php?'.$_SERVER['QUERY_STRING'];
+ $authplugin = get_auth_plugin('ldap');
+ if (empty($authplugin->config->ntlmsso_enabled)) {
+ redirect($CFG->wwwroot . '/login/index.php');
+ } else {
+ redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_attempt.php');
+ }
+}
+
+require_once($CFG->libdir.'/adminlib.php');
+require_once('cpdactivitymaintenance_filter_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+
+require_login();
+
+require_capability('report/fitandproper:viewcpdactivitymaintenance', get_context_instance(CONTEXT_SYSTEM));
+
+$partyid = required_param('partyid',PARAM_TEXT);
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymaintenance.php";
+$url_manager = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymanager.php";
+
+// Print the header.
+admin_externalpage_setup('cpdactivitymaintenance');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('cpdactivitymaintenance_heading', 'report_fitandproper'));
+
+$display = false;
+//echo $OUTPUT->notification('test');
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+if(isset($user_details->id))
+{
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('cpdactivitymaintenance_usernotfound', 'report_fitandproper'));
+}
+
+if($display)
+{
+ /*
+ * Display filter
+ */
+ $filter_form = new cpdactivitymaintenance_filter_form(null,array('partyid'=>$partyid));
+ echo $OUTPUT->box_start('filterlist');
+ echo '';
+ echo ''.get_string('cpdactivitymaintenance_filter_head', 'report_fitandproper').' ';
+ echo '';
+ $filter_form->display();
+ echo '
';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+ /*
+ * Get list of institutions from database and apply filters if neccesary
+ */
+ if($fdata = $filter_form->get_data())
+ {
+ if(isset($fdata->enabled))
+ {
+ $where= '';
+ $params = array();
+ $where = 'completed >= ? AND completed <= ? and moodle_user_id = ?';
+ $params = array($fdata->date_from,$fdata->date_to,$user_details->id);
+ $where .= ' AND deleted = 0';
+ $activities = $DB->get_records_select('user_cpd_activity',$where,$params,'completed DESC');
+ }else
+ {
+ //no filter selected so get all records
+ $activities = $DB->get_records('user_cpd_activity',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+ }
+ else
+ {
+ //no filter selected so get all records
+ $activities = $DB->get_records('user_cpd_activity',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+
+ /*
+ * Display intitions list table
+ */
+
+ echo $OUTPUT->box_start('cpdactivitymaintenancelist');
+ echo 'CPD Activities for '.$user_details->firstname.' '.$user_details->lastname.'
';
+ echo '';
+ echo 'View user Regulatory Exam Results ';
+ echo ' ';
+ echo 'View user Qualification ';
+ echo '
';
+ echo ''.get_string('cpdactivitymaintenance_addnew', 'report_fitandproper').'
';
+
+
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('cpdactivitymaintenance_tableheadcode', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheaddesc', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadcompleted', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadinstitution', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadhours', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadcategories', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadedit', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheaddelete', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadproof', 'report_fitandproper'));
+
+ $r = array();
+
+ $context = get_system_context();
+ $fs = get_file_storage();
+
+ if(isset($activities) && count($activities) > 0)
+ {
+ foreach($activities as $a)
+ {
+ //get the cpd activity details
+ $a_details = $DB->get_record('cpd_activity',array('id'=>$a->cpd_activity_id),'id,code,name,hours');
+ //get institution details
+ $i_details = $DB->get_record('institution',array('id'=>$a->institution_id),'name');
+ //get sub category ids
+ $sub_cats = $DB->get_records_sql('SELECT ac.id,c.code,c.name FROM {cpd_activity_fais_sub_cat} ac INNER JOIN {fais_sub_category} c ON (ac.fais_sub_category_id = c.id) WHERE ac.cpd_activity_id = ?',array($a_details->id));
+ $subcatids = '';
+// var_dump($sub_cats);
+ $i = 1;
+ foreach($sub_cats as $sid=>$sdata)
+ {
+ $subcatids .= $i < count($sub_cats) ? "$sdata->code. $sdata->name " : "$sdata->code. $sdata->name";
+ }
+ $subcatids = rtrim($subcatids,', ');
+
+ $edit = ' ';
+ $delete = ' ';
+
+ //check if file is there
+ if($a->attendance_file != null)
+ {
+ $viewproof = 'View ';
+ }else
+ {
+ $viewproof = 'None';
+ }
+ $row = new html_table_row(array($a_details->code,$a_details->name,date('Y-m-d',$a->completed),$i_details->name,$a_details->hours,$subcatids,$edit,$delete,$viewproof));
+ if($a->enabled == 0) $row->attributes = array('class'=>'faiscategorydisabled');
+ $table->data[] = $row;
+ //$table->data[] = array($i->code,$i->name,$edit,$delete);
+ }
+ }
+ else
+ {
+ $table->data[] = array(get_string('cpdactivitymaintenance_tablenorows', 'report_fitandproper'));
+ }
+ echo html_writer::table($table);
+
+ echo ''.get_string('cpdactivitymaintenance_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+// Footer.
+echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivitymaintenance.php.B4_PATCH b/admin/report/fitandproper/cpdactivitymaintenance.php.B4_PATCH
new file mode 100644
index 00000000000..4c0c54d2350
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivitymaintenance.php.B4_PATCH
@@ -0,0 +1,177 @@
+id === 0) {
+ $SESSION->wantsurl = $CFG->wwwroot . '/admin/report/fitandproper/cpdactivitymaintenance.php?'.$_SERVER['QUERY_STRING'];
+ redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_attempt.php');
+}
+
+require_once($CFG->libdir.'/adminlib.php');
+require_once('cpdactivitymaintenance_filter_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+
+require_login();
+
+require_capability('report/fitandproper:viewcpdactivitymaintenance', get_context_instance(CONTEXT_SYSTEM));
+
+$partyid = required_param('partyid',PARAM_TEXT);
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymaintenance.php";
+$url_manager = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymanager.php";
+
+// Print the header.
+admin_externalpage_setup('cpdactivitymaintenance');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('cpdactivitymaintenance_heading', 'report_fitandproper'));
+
+$display = false;
+//echo $OUTPUT->notification('test');
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+if(isset($user_details->id))
+{
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('cpdactivitymaintenance_usernotfound', 'report_fitandproper'));
+}
+
+if($display)
+{
+ /*
+ * Display filter
+ */
+ $filter_form = new cpdactivitymaintenance_filter_form(null,array('partyid'=>$partyid));
+ echo $OUTPUT->box_start('filterlist');
+ echo '';
+ echo ''.get_string('cpdactivitymaintenance_filter_head', 'report_fitandproper').' ';
+ echo '';
+ $filter_form->display();
+ echo '
';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+ /*
+ * Get list of institutions from database and apply filters if neccesary
+ */
+ if($fdata = $filter_form->get_data())
+ {
+ if(isset($fdata->enabled))
+ {
+ $where= '';
+ $params = array();
+ $where = 'completed >= ? AND completed <= ? and moodle_user_id = ?';
+ $params = array($fdata->date_from,$fdata->date_to,$user_details->id);
+ $where .= ' AND deleted = 0';
+ $activities = $DB->get_records_select('user_cpd_activity',$where,$params,'completed DESC');
+ }else
+ {
+ //no filter selected so get all records
+ $activities = $DB->get_records('user_cpd_activity',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+ }
+ else
+ {
+ //no filter selected so get all records
+ $activities = $DB->get_records('user_cpd_activity',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+
+ /*
+ * Display intitions list table
+ */
+
+ echo $OUTPUT->box_start('cpdactivitymaintenancelist');
+ echo 'CPD Activities for '.$user_details->firstname.' '.$user_details->lastname.'
';
+ echo '';
+ echo 'View user Regulatory Exam Results ';
+ echo ' ';
+ echo 'View user Qualification ';
+ echo '
';
+ echo ''.get_string('cpdactivitymaintenance_addnew', 'report_fitandproper').'
';
+
+
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('cpdactivitymaintenance_tableheadcode', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheaddesc', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadcompleted', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadinstitution', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadhours', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadcategories', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadedit', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheaddelete', 'report_fitandproper'),
+ get_string('cpdactivitymaintenance_tableheadproof', 'report_fitandproper'));
+
+ $r = array();
+
+ $context = get_system_context();
+ $fs = get_file_storage();
+
+ if(isset($activities) && count($activities) > 0)
+ {
+ foreach($activities as $a)
+ {
+ //get the cpd activity details
+ $a_details = $DB->get_record('cpd_activity',array('id'=>$a->cpd_activity_id),'id,code,name,hours');
+ //get institution details
+ $i_details = $DB->get_record('institution',array('id'=>$a->institution_id),'name');
+ //get sub category ids
+ $sub_cats = $DB->get_records_sql('SELECT ac.id,c.code,c.name FROM {cpd_activity_fais_sub_cat} ac INNER JOIN {fais_sub_category} c ON (ac.fais_sub_category_id = c.id) WHERE ac.cpd_activity_id = ?',array($a_details->id));
+ $subcatids = '';
+// var_dump($sub_cats);
+ $i = 1;
+ foreach($sub_cats as $sid=>$sdata)
+ {
+ $subcatids .= $i < count($sub_cats) ? "$sdata->code. $sdata->name " : "$sdata->code. $sdata->name";
+ }
+ $subcatids = rtrim($subcatids,', ');
+
+ $edit = ' ';
+ $delete = ' ';
+
+ //check if file is there
+ if($a->attendance_file != null)
+ {
+ $viewproof = 'View ';
+ }else
+ {
+ $viewproof = 'None';
+ }
+ $row = new html_table_row(array($a_details->code,$a_details->name,date('Y-m-d',$a->completed),$i_details->name,$a_details->hours,$subcatids,$edit,$delete,$viewproof));
+ if($a->enabled == 0) $row->attributes = array('class'=>'faiscategorydisabled');
+ $table->data[] = $row;
+ //$table->data[] = array($i->code,$i->name,$edit,$delete);
+ }
+ }
+ else
+ {
+ $table->data[] = array(get_string('cpdactivitymaintenance_tablenorows', 'report_fitandproper'));
+ }
+ echo html_writer::table($table);
+
+ echo ''.get_string('cpdactivitymaintenance_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+// Footer.
+echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivitymaintenance_filter_form.php b/admin/report/fitandproper/cpdactivitymaintenance_filter_form.php
new file mode 100644
index 00000000000..885107b9324
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivitymaintenance_filter_form.php
@@ -0,0 +1,27 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the filter form for cpd activity maintenance
+ */
+class cpdactivitymaintenance_filter_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+ $partyid = $this->_customdata['partyid'];
+
+ $mform->addElement('checkbox', 'enabled', get_string('cpdactivitymaintenance_filter_enable', 'report_fitandproper'));
+ $mform->addElement('date_selector', 'date_from', get_string('cpdactivitymaintenance_filter_datefrom', 'report_fitandproper'));
+ $mform->addElement('date_selector', 'date_to', get_string('cpdactivitymaintenance_filter_dateto', 'report_fitandproper'));
+ $mform->addElement('hidden','partyid',$partyid);
+
+ $buttonarray=array();
+ $buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('cpdactivitymaintenance_filter_submit', 'report_fitandproper'));
+ $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
+ $mform->closeHeaderBefore('buttonar');
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivitymanager.php b/admin/report/fitandproper/cpdactivitymanager.php
new file mode 100644
index 00000000000..7cfdfd351f7
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivitymanager.php
@@ -0,0 +1,222 @@
+libdir.'/adminlib.php');
+//require_once('cpdactivityadmin_edit_form.php');
+require_once('cpdactivitymanager_edit_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewcpdactivitymanager', get_context_instance(CONTEXT_SYSTEM));
+
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+$partyid = required_param('partyid',PARAM_TEXT);
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymanager.php";
+$url_maintenance = "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymaintenance.php?partyid=".$partyid;
+$context = get_system_context();
+
+// Print the header.
+admin_externalpage_setup('cpdactivitymanager');
+echo $OUTPUT->header();
+
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+
+$display = false;
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+
+if(isset($user_details->id))
+{
+ echo $OUTPUT->heading(get_string('cpdactivitymanager_heading', 'report_fitandproper') . ' For ' . $user_details->firstname . ' ' . $user_details->lastname);
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('cpdactivitymaintenance_usernotfound', 'report_fitandproper'));
+}
+
+/*
+ * Check if user requested an add or edit institution
+ */
+if($display)
+{
+ if($op == 'add' || $op == 'edit')
+ {
+
+ // Include the required JavaScript.
+ $jsmodule = array(
+ 'name' => 'report_fitandproper',
+ 'fullpath' => '/admin/report/fitandproper/module_cpdactivitymanager.js'); //on this line you are loading three other YUI modules
+ $PAGE->requires->js_init_call('M.report_fitandproper.init',null,false,$jsmodule);
+
+ $edit_form = new cpdactivitymanager_edit_form(null,array('partyid'=>$partyid,'op'=>$op,'id'=>$id));
+ $data = $edit_form->get_data();
+
+ if($edit_form->is_cancelled())
+ {
+ redirect($url_maintenance);
+ }
+ if($data)
+ {
+ /*
+ * Check if user is doing an edit
+ */
+ if($op == 'edit')
+ {
+ //edit
+ //create cpd activity object
+ $record = new stdClass();
+ if($data->id != null && $data->id > 0)
+ {
+ $record->id = $data->id;
+ }
+ $record->cpd_activity_id = $data->activity;
+ $record->institution_id = $data->institution;
+ $record->completed = $data->date_completed;
+ $record->moodle_user_id = $user_details->id;
+ //$record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->enabled = 1;
+ $record->timemodified = time();
+ $DB->update_record('user_cpd_activity', $record, false, false);
+
+ /*
+ * Save the uploaded file
+ */
+ if($edit_form->get_file_content('proof') != false)
+ {
+ file_save_draft_area_files($data->proof, $context->id, 'report_fitandproper', 'user_cpdactivity', $record->id);
+ $filename = $edit_form->get_new_filename('proof');
+ $DB->set_field('user_cpd_activity', 'attendance_file', $filename, array('id'=>$record->id));
+ }else
+ {
+ //remove file if needed
+ $filename = $DB->get_field('user_cpd_activity','attendance_file',array('id'=>$record->id));
+ if($filename)
+ {
+ $file = $fs->get_file($context->id, 'report_fitandproper', 'user_cpdactivity', $record->id, '/', $filename);
+ if($file)
+ {
+ $file->delete();
+ }
+ $DB->set_field('user_cpd_activity', 'attendance_file', null, array('id'=>$record->id));
+ }
+ }
+
+ // Log.
+ add_to_log(SITEID, 'User CPD Activity', ": Edit", "report/fitandproper/cpdactivitymaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+ redirect($url_maintenance);
+ }
+
+ /*
+ * Add a new user qualification to the database
+ */
+ if($op == 'add')
+ {
+ //save
+ //create user cpd activity object
+
+ $record = new stdClass();
+
+ $record->cpd_activity_id = $data->activity;
+ $record->institution_id = $data->institution;
+ $record->completed = $data->date_completed;
+ $record->moodle_user_id = $user_details->id;
+ $record->enabled = 1;
+ $record->timecreated = time();
+ $ins_id = $DB->insert_record('user_cpd_activity', $record, true, false);
+
+ /*
+ * Save the uploaded file
+ */
+ file_save_draft_area_files($data->proof, $context->id, 'report_fitandproper', 'user_cpdactivity', $ins_id);
+ $filename = $edit_form->get_new_filename('proof');
+ $DB->set_field('user_cpd_activity', 'attendance_file', $filename, array('id'=>$ins_id));
+
+ // Log.
+ add_to_log(SITEID, 'User CPD Activity', ": Add", "report/fitandproper/cpdactivitymaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+
+ redirect($url_maintenance);
+ }
+ }else
+ {
+ if($op == 'edit')
+ {
+ $draftitemid = file_get_submitted_draft_itemid('proof');
+ file_prepare_draft_area($draftitemid, $context->id, 'report_fitandproper', 'user_cpdactivity', $id, array('subdirs' => 0, 'maxbytes' => 800000, 'maxfiles' => 50));
+ $entry->proof = $draftitemid;
+ $edit_form->set_data($entry);
+ }
+ $edit_form->display();
+ }
+ $display = false;
+ }
+ elseif($op == 'delete')
+ {
+ /*
+ * Handle the deletion of User CPD Activities
+ */
+ if($id != null)
+ {
+ $record = new stdClass();
+ $record->id = $id;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('user_cpd_activity', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'User CPD Activity', ": Delete", "report/fitandproper/cpdactivitymaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+ }
+
+ redirect($url_maintenance);
+ }
+}
+//echo $OUTPUT->notification('test');
+
+// Footer.
+echo $OUTPUT->footer();
+
+/*
+ * Function to save the uploaded file
+ * @param $qid integer The saved user qualification id
+ * @param $file The uploaded temporary file
+ * @param $file_name The uploaded file name
+ */
+function qualificationmanager_save_proof($qid,$file,$file_name)
+{
+ global $DB,$CFG;
+
+ /*
+ * Check if directory exist
+ */
+ if(!file_exists($CFG->dataroot.'/user_qualification_proof'))
+ {
+ mkdir($CFG->dataroot.'/user_qualification_proof');
+ }
+
+ /*
+ * Move file
+ */
+ $extension = substr(strrchr($file_name,'.'),1);
+
+ if(rename($file,$CFG->dataroot.'/user_qualification_proof/'.$qid.'.'.$extension))
+ {
+ return $qid.'.'.$extension;
+ }else
+ {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivitymanager_ajax.php b/admin/report/fitandproper/cpdactivitymanager_ajax.php
new file mode 100644
index 00000000000..3d33bf98a28
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivitymanager_ajax.php
@@ -0,0 +1,42 @@
+libdir.'/adminlib.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewcpdactivitymanager', get_context_instance(CONTEXT_SYSTEM));
+
+$aid = (int)$_GET['aid'];
+
+if($aid > 0)
+{
+ $sql = 'SELECT sc.name AS subcategory,c.name AS topcategory,a.hours FROM {cpd_activity} a INNER JOIN {cpd_activity_fais_sub_cat} ascl ON (ascl.cpd_activity_id = a.id) INNER JOIN {fais_sub_category} sc ON (ascl.fais_sub_category_id = sc.id) INNER JOIN {fais_category} c ON (sc.fais_category_id = c.id) WHERE a.id = ? AND sc.deleted != 1';
+
+ $sub_cats = $DB->get_records_sql($sql,array($aid));
+ $count = count($sub_cats);
+ $return = array();
+ if($count > 0)
+ {
+ $return['count'] = $count;
+ foreach($sub_cats as $s)
+ {
+ $return['hours'] = $s->hours;
+ $return['category'] = $s->topcategory;
+ $return['subcategories'][] = $s->subcategory;
+ }
+
+ print json_encode($return);
+ }else
+ {
+ print json_encode(array('count'=>0));
+ }
+}
+?>
\ No newline at end of file
diff --git a/admin/report/fitandproper/cpdactivitymanager_edit_form.php b/admin/report/fitandproper/cpdactivitymanager_edit_form.php
new file mode 100644
index 00000000000..b6b5c27fb92
--- /dev/null
+++ b/admin/report/fitandproper/cpdactivitymanager_edit_form.php
@@ -0,0 +1,120 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the add/edit for user cpd activity maintenance
+ */
+class cpdactivitymanager_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+ $partyid = $this->_customdata['partyid'];
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+
+ /*
+ * Get all the activities
+ */
+ $activities = $DB->get_records('cpd_activity',array('enabled'=>1,'deleted'=>0),'name','id,name,hours');
+
+ $a_options = array(0=>'Select an Activity');
+ if($activities)
+ {
+ foreach($activities as $a)
+ {
+ $a_options[$a->id] = $a->name;
+ }
+ }
+
+ /*
+ * Get all the institutions
+ */
+ $institutions = $DB->get_records('institution',array('enabled'=>1,'deleted'=>0),'name','id,name');
+ $i_options = array(0=>'Select a Institution');
+ if($institutions)
+ {
+ foreach($institutions as $i)
+ {
+ $i_options[$i->id] = $i->name;
+ }
+ }
+
+ $sub_categories = array();
+ /*
+ * Edit form data
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $u_activity = $DB->get_record('user_cpd_activity',array('id'=>$id));
+
+ $mform->setDefault('activity', $u_activity->cpd_activity_id);
+ $mform->setDefault('date_completed', $u_activity->completed);
+ $mform->setDefault('institution', $u_activity->institution_id);
+
+ $sql = 'SELECT sc.id as subid,sc.name AS subcategory,c.name AS topcategory,a.hours FROM {cpd_activity} a INNER JOIN {cpd_activity_fais_sub_cat} ascl ON (ascl.cpd_activity_id = a.id) INNER JOIN {fais_sub_category} sc ON (ascl.fais_sub_category_id = sc.id) INNER JOIN {fais_category} c ON (sc.fais_category_id = c.id) WHERE a.id = ? AND sc.deleted != 1';
+
+ $sub_cats = $DB->get_records_sql($sql,array($u_activity->cpd_activity_id));
+ $count = count($sub_cats);
+
+ if($count > 0)
+ {
+ foreach($sub_cats as $s)
+ {
+ $sub_categories[$s->subid] = $s->subcategory;
+ $hours = $s->hours;
+ $category = $s->topcategory;
+ }
+ }
+ $mform->setDefault('category',$category);
+ $mform->setDefault('hours',$hours);
+ }else
+ {
+ $mform->setDefault('category','Please select an Activity');
+ }
+
+ $mform->addElement('select', 'activity', get_string('cpdactivitymanager_activity', 'report_fitandproper'), $a_options);
+ $mform->addRule('activity', null, 'required', null, 'client');
+ $mform->addRule('activity', 'You must select a CPD Activity', 'nonzero', null, 'client');
+
+ $mform->addElement('date_selector', 'date_completed', get_string('cpdactivitymanager_completed', 'report_fitandproper'));
+ $mform->addRule('date_completed', null, 'required', null, 'client');
+
+ $mform->addElement('select', 'institution', get_string('cpdactivitymanager_institution', 'report_fitandproper'), $i_options);
+ $mform->addRule('institution', null, 'required', null, 'client');
+ $mform->addRule('institution', 'You must select an Institution', 'nonzero', null, 'client');
+
+ $mform->addElement('text', 'hours', get_string('cpdactivitymanager_hours', 'report_fitandproper'),array('disabled'=>'disabled'));
+
+ $mform->addElement('text', 'category', get_string('cpdactivity_category', 'report_fitandproper'),array('disabled'=>'disabled'));
+
+ $subselect = $mform->addElement('select', 'subcategory', get_string('cpdactivity_subcategory', 'report_fitandproper'), $sub_categories,array('disabled'=>'disabled'));
+ $subselect->setMultiple(true);
+
+ $mform->addElement('filepicker', 'proof', get_string('cpdactivitymanager_proof', 'report_fitandproper'), null, array('maxbytes' => 8000000, 'accepted_types' => array('*.pdf','*.docx','*.doc','*.rtf','*.jpg','*.gif','*.tif','*.png')));
+ $mform->addRule('proof', null, 'required', null, 'server');
+
+ $mform->addElement('hidden','partyid',$partyid);
+ $mform->addElement('hidden','op',$op);
+ $mform->addElement('hidden','id',$id);
+
+
+ $this->add_action_buttons(true,get_string('qualificationmanager_submit', 'report_fitandproper'));
+
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+ $db_file = $DB->count_records('files',array('itemid'=>$data['proof']));
+ if ($db_file == 0)
+ {
+ $errors['proof'] = get_string('required');
+ }
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/db/access.php b/admin/report/fitandproper/db/access.php
new file mode 100644
index 00000000000..cf997b45762
--- /dev/null
+++ b/admin/report/fitandproper/db/access.php
@@ -0,0 +1,92 @@
+ array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:deletefaiscategories' => array(
+ 'captype' => 'write',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:viewinstitutions' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:deleteinstitutions' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:viewqualifications' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:deletequalifications' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:viewcpdactivities' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:deletecpdactivities' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:viewqualificationmaintenance' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW
+ ),
+ ),
+ 'report/fitandproper:viewqualificationmanager' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW
+ ),
+ ),
+ 'report/fitandproper:viewcpdactivitymaintenance' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW
+ ),
+ ),
+ 'report/fitandproper:viewcpdactivitymanager' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW
+ ),
+ ),
+
+ 'report/fitandproper:viewreexamresultsmaintenance' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW
+ ),
+ ),
+
+ 'report/fitandproper:viewreexamresultsmanager' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM,
+ 'archetypes' => array(
+ 'manager' => CAP_ALLOW
+ ),
+ ),
+
+ 'report/fitandproper:viewreexams' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:deletereexams' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ ),
+ 'report/fitandproper:viewreresults' => array(
+ 'captype' => 'wtite',
+ 'contextlevel' => CONTEXT_SYSTEM
+ )
+);
\ No newline at end of file
diff --git a/admin/report/fitandproper/db/install.xml b/admin/report/fitandproper/db/install.xml
new file mode 100644
index 00000000000..a3dd4d4ad02
--- /dev/null
+++ b/admin/report/fitandproper/db/install.xml
@@ -0,0 +1,227 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/admin/report/fitandproper/db/upgrade.php b/admin/report/fitandproper/db/upgrade.php
new file mode 100644
index 00000000000..bfc99ea68e1
--- /dev/null
+++ b/admin/report/fitandproper/db/upgrade.php
@@ -0,0 +1,31 @@
+get_manager();
+ $result = true;
+
+ if ($oldversion < 2011040123) {
+
+ // Adding code field to fais_category table
+ $code_field = new xmldb_field('code', XMLDB_TYPE_CHAR, '255', null, null, null, 'name');
+ $fais_categories = new xmldb_table('fais_category');
+ if(!$dbman->field_exists($fais_categories, $code_field)) {
+ $dbman->add_field($fais_categories, $code_field);
+ }
+
+
+ // Adding code field to fais_sub_category table
+ $code_field = new xmldb_field('code', XMLDB_TYPE_CHAR, '255', null, null, null, 'name');
+ $fais_sub_categories = new xmldb_table('fais_sub_category');
+ if(!$dbman->field_exists($fais_sub_categories, $code_field)) {
+ $dbman->add_field($fais_sub_categories, $code_field);
+ }
+
+ upgrade_plugin_savepoint(true, 2011040123, 'report', 'fitandproper');
+ }
+
+ return $result;
+}
+?>
diff --git a/admin/report/fitandproper/faiscategories.php b/admin/report/fitandproper/faiscategories.php
new file mode 100644
index 00000000000..ead5e10c248
--- /dev/null
+++ b/admin/report/fitandproper/faiscategories.php
@@ -0,0 +1,254 @@
+libdir.'/adminlib.php');
+require_once('faiscategorylinks.php');
+require_once('faiscategoryadmin_edit_form.php');
+require_once('faiscategoryadmin_links_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_capability('report/fitandproper:viewfaiscategories', get_context_instance(CONTEXT_SYSTEM));
+
+// Print the header.
+admin_externalpage_setup('fiascategoryadmin');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('faiscategoryadmin_heading', 'report_fitandproper'));
+
+ //check if user wants to edit or delete a category
+$op = optional_param('op', null,PARAM_TEXT);
+$category = optional_param('category', null,PARAM_INTEGER);
+$type = optional_param('type', null,PARAM_TEXT);
+$save_now = optional_param('save_now', null,PARAM_INTEGER);
+
+
+//$saved = display_category_edit_form($op,$category,$type);
+
+/**
+ * Displays a form to edit/add a FAIS category
+ */
+
+if($op == 'edit' || $op == 'add')
+{
+ global $DB;
+
+ $saved = false;
+ if($op == 'add')
+ {
+ $edit_form = new faiscategoryadmin_edit_form(null,array('top_category'=>$category,'op'=>'add'));
+
+ //save data if form submitted
+ if($edit_form->is_cancelled())
+ {
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }
+ if ($data = $edit_form->get_data())
+ {
+ if($data->parent > 0)
+ {
+ $record = new stdClass();
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->description = $data->description;
+ $record->fais_category_id = (int)$data->parent;
+ $record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->timecreated = time();
+ $DB->insert_record('fais_sub_category', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'FAIS Sub Category', ": Add", "report/fitandproper/faiscategories.php",$record->name);
+
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }else
+ {
+ $record = new stdClass();
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->description = $data->description;
+ $record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->timecreated = time();
+ $DB->insert_record('fais_category', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'FAIS Category', ": Add", "report/fitandproper/faiscategories.php",$record->name);
+
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }
+ }else
+ {
+ echo '';
+ $edit_form->display();
+ echo '
';
+ }
+ }else
+ {
+ //display category edit form
+
+ if($type == 'top')
+ {
+ $db_table = 'fais_category';
+ }else
+ {
+ $db_table = 'fais_sub_category';
+ }
+
+ $edit_category = $DB->get_record($db_table,array('id'=>$category));
+ $top_category = (isset($edit_category->fais_category_id)) ? $edit_category->fais_category_id : 0;
+
+ $links_form = new faiscategoryadmin_links_form(null);
+
+ $edit_form = new faiscategoryadmin_edit_form(null,array('top_category'=>$top_category,'op'=>'edit','edit_category'=>$edit_category,'type'=>$type));
+
+ if($links_form->is_cancelled())
+ {
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }elseif($data = $links_form->get_data())
+ {
+ if($data->type == 'top')
+ {
+ $db_table = 'fais_category';
+ $log = 'FAIS Category';
+ }else
+ {
+ $db_table = 'fais_sub_category';
+ $log = 'FAIS Sub Category';
+ }
+
+ if($data->type == 'top' && $data->parent > 0)
+ {
+ //move top category to sub category table
+ $record = new stdClass();
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->fais_category_id = (int)$data->parent;
+ $record->description = $data->description;
+ $record->enabled = (int)$data->enabled;
+ $record->timecreated = time();
+ $record->timemodified = time();
+ $insert_id = $DB->insert_record('fais_sub_category', $record);
+
+ if($insert_id)
+ {
+ $record->id = $data->category;
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('fais_category', $record);
+
+ // Log.
+ add_to_log(SITEID, $log, ": Edit", "report/fitandproper/faiscategories.php",$record->name);
+
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }
+
+ }elseif($data->type == 'sub' && $data->parent == 0)
+ {
+ //move sub category to top category
+ $record = new stdClass();
+
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->description = $data->description;
+ $record->enabled = (int)$data->enabled;
+ $record->timecreated = time();
+ $record->timemodified = time();
+ $insert_id = $DB->insert_record('fais_category', $record);
+
+ if($insert_id)
+ {
+ $record->id = $data->category;
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('fais_sub_category', $record);
+
+ // Log.
+ add_to_log(SITEID, $log, ": Edit", "report/fitandproper/faiscategories.php",$record->name);
+
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }
+ }else
+ {
+ $record = new stdClass();
+ $record->id = $data->category;
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->description = $data->description;
+ $record->enabled = (int)$data->enabled;
+ $record->timemodified = time();
+ if($db_table == 'fais_sub_category') $record->fais_category_id = $data->parent;
+ $DB->update_record($db_table, $record);
+
+ // Log.
+ add_to_log(SITEID, $log, ": Edit", "report/fitandproper/faiscategories.php",$record->name);
+
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }
+ }
+
+ if($edit_form->is_cancelled())
+ {
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }elseif ($data = $edit_form->get_data())
+ {
+ display_category_links($data,$edit_category);
+ }else
+ {
+ echo '';
+ $edit_form->display();
+ echo '
';
+ }
+ }
+}elseif($op == 'delete')
+{
+ require_capability('report/fitandproper:deletefaiscategories', get_context_instance(CONTEXT_SYSTEM));
+
+ //delete category
+ $db_table = ($type == 'top') ? 'fais_category' : 'fais_sub_category';
+
+ $delete_category = $DB->get_record($db_table,array('id'=>$category));
+
+ $links_form = new faiscategoryadmin_links_form(null);
+ if($links_form->is_cancelled())
+ {
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }elseif ($data = $links_form->get_data())
+ {
+ $record = new stdClass();
+ $record->id = $data->category;
+ $record->code = $data->code;
+ $record->name = $data->name;
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+
+ if($data->type == 'top')
+ {
+ $db_table = 'fais_category';
+ $log = 'FAIS Category';
+ }else
+ {
+ $db_table = 'fais_sub_category';
+ $log = 'FAIS Sub Category';
+ }
+ $DB->update_record($db_table, $record);
+
+ // Log.
+ add_to_log(SITEID, $log, ": Delete", "report/fitandproper/faiscategories.php",$record->name);
+
+ redirect("$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php");
+ }else
+ {
+ $form_data = new stdClass();
+ $form_data->category = $category;
+ $form_data->op = 'delete';
+ $form_data->type = $type;
+
+ display_category_links($form_data,$delete_category);
+ }
+}
+
+// Footer.
+echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/admin/report/fitandproper/faiscategoryadmin.php b/admin/report/fitandproper/faiscategoryadmin.php
new file mode 100644
index 00000000000..82d83ce780f
--- /dev/null
+++ b/admin/report/fitandproper/faiscategoryadmin.php
@@ -0,0 +1,81 @@
+libdir.'/adminlib.php');
+//require_once('faiscategorylinks.php');
+//require_once('faiscategoryadmin_edit_form.php');
+//require_once('faiscategoryadmin_links_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewfaiscategories', get_context_instance(CONTEXT_SYSTEM));
+
+// Print the header.
+admin_externalpage_setup('fiascategoryadmin');
+
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('faiscategoryadmin_heading', 'report_fitandproper'));
+
+ //print into text
+ echo '', get_string('faiscategoryadmin_intro', 'report_fitandproper') , '
';
+
+ //get all enabled FAIS categories
+ $fais_categories = $DB->get_records('fais_category',array('deleted'=>0),'name');
+
+ //display table with categories
+ echo '';
+
+ //add new category button
+ echo '';
+ echo '';
+ echo '
';
+
+// Footer.
+echo $OUTPUT->footer();
+
diff --git a/admin/report/fitandproper/faiscategoryadmin_edit_form.php b/admin/report/fitandproper/faiscategoryadmin_edit_form.php
new file mode 100644
index 00000000000..ee42bc75bd0
--- /dev/null
+++ b/admin/report/fitandproper/faiscategoryadmin_edit_form.php
@@ -0,0 +1,123 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the FAIS categories add/edit form
+ */
+class faiscategoryadmin_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $top_category = $this->_customdata['top_category'];
+ $op = $this->_customdata['op'];
+ $edit_category = (isset($this->_customdata['edit_category'])) ? $this->_customdata['edit_category'] : null;
+ $type = (isset($this->_customdata['type'])) ? $this->_customdata['type'] : null;
+
+ //get list of top level categories
+ $fais_categories = $DB->get_records('fais_category',array('deleted'=>0,'enabled'=>1),'name','id,name');
+ $category_list = array('0'=>'Top');
+ foreach($fais_categories as $category)
+ {
+ $category_list[$category->id] = $category->name;
+ }
+
+ $header = ($op == 'edit') ? 'Edit' : 'Add';
+
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('select', 'parent', get_string('faiscategory_parent', 'report_fitandproper'),$category_list);
+
+ $mform->addElement('text', 'name', get_string('faiscategory_name', 'report_fitandproper'));
+ $mform->addRule('name', null, 'required', null, 'client');
+ $mform->addRule('name', null, 'maxlength', 255, 'client');
+
+ $mform->addElement('text', 'code', get_string('faiscategory_code', 'report_fitandproper'));
+ $mform->addRule('code', null, 'required', null, 'client');
+
+ $mform->addElement('textarea', 'description', get_string('faiscategory_description', 'report_fitandproper'),'rows=5 cols="40"');
+ $mform->addRule('description', null, 'maxlength', 255, 'client');
+ $mform->addElement('checkbox', 'enabled', get_string('faiscategory_enabled', 'report_fitandproper'));
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'type', $type);
+ $mform->addElement('hidden', 'category');
+
+ $mform->setDefault('parent', $top_category);
+
+ if($op == 'edit')
+ {
+ $mform->setDefault('category', $edit_category->id);
+ $mform->setDefault('name', $edit_category->name);
+ $mform->setDefault('code', $edit_category->code);
+ $mform->setDefault('description', $edit_category->description);
+ $mform->setDefault('enabled', $edit_category->enabled);
+ }else
+ {
+ $mform->setDefault('enabled', 1);
+ }
+
+ $this->add_action_buttons(true,get_string('faiscategory_submit', 'report_fitandproper'));
+
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+ //check for duplicate name
+
+ if($data['parent'] == 0)
+ {
+ if(isset($data['category']))
+ {
+ $check_name = $DB->count_records_select('fais_category','deleted = 0 and name = ? and id != ?',array($data['name'],$data['category']));
+ $check_code = $DB->count_records_select('fais_category','deleted = 0 and code = ? and id != ?',array($data['code'],$data['category']));
+ }else
+ {
+
+ $check_name = $DB->count_records_select('fais_category','deleted = 0 and name = ?',array($data['name']));
+ $check_code = $DB->count_records_select('fais_category','deleted = 0 and code = ?',array($data['code']));
+ }
+
+ if($check_name > 0)
+ {
+ $errors['name'] = get_string('faiscategoryadmin_submit_duplicate_name', 'report_fitandproper');
+ }
+ if($check_code > 0)
+ {
+ $errors['code'] = get_string('faiscategoryadmin_submit_duplicate_code', 'report_fitandproper');
+ }
+ }else
+ {
+ if(isset($data['category']))
+ {
+ $check_name = $DB->count_records_select('fais_sub_category','deleted = 0 and name = ? and id != ?',array($data['name'],$data['category']));
+ $check_code = $DB->count_records_select('fais_sub_category','deleted = 0 and code = ? and id != ?',array($data['code'],$data['category']));
+ }else
+ {
+ $check_name = $DB->count_records_select('fais_sub_category','deleted = 0 and name = ?',array($data['name']));
+ $check_code = $DB->count_records_select('fais_sub_category','deleted = 0 and code = ?',array($data['code']));
+ }
+ $checktop_name = $DB->count_records_select('fais_category','deleted = 0 and name = ?',array($data['name']));
+ $checktop_code = $DB->count_records_select('fais_category','deleted = 0 and code = ?',array($data['code']));
+
+ if($check_name > 0 || $checktop_name > 0)
+ {
+ $errors['name'] = get_string('faiscategoryadmin_submit_duplicate_name', 'report_fitandproper');
+ }
+ if($check_code > 0 || $checktop_code > 0)
+ {
+ $errors['code'] = get_string('faiscategoryadmin_submit_duplicate_code', 'report_fitandproper');
+ }
+ }
+ //$errors['name'] = get_string('faiscategoryadmin_submit_duplicate_name', 'report_fitandproper');
+
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/faiscategoryadmin_links_form.php b/admin/report/fitandproper/faiscategoryadmin_links_form.php
new file mode 100644
index 00000000000..7fba480ec4e
--- /dev/null
+++ b/admin/report/fitandproper/faiscategoryadmin_links_form.php
@@ -0,0 +1,67 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the FAIS categories add/edit links report form
+ */
+class faiscategoryadmin_links_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $edit_form = $this->_customdata['edit_form'];
+ $can_save = $this->_customdata['can_save'];
+
+ if(!isset($edit_form))
+ {
+ $edit_form->parent = '';
+ $edit_form->name = '';
+ $edit_form->code = '';
+ $edit_form->description = '';
+ $edit_form->enabled = '';
+ $edit_form->op = '';
+ $edit_form->type = '';
+ $edit_form->category = '';
+ $edit_form->savenow = '';
+ }
+
+ if(!isset($edit_form->parent)) $edit_form->parent = '';
+ if(!isset($edit_form->name)) $edit_form->name = '';
+ if(!isset($edit_form->code)) $edit_form->code = '';
+ if(!isset($edit_form->description)) $edit_form->description = '';
+ if(!isset($edit_form->enabled)) $edit_form->enabled = 0;
+
+ $mform->addElement('hidden', 'parent', $edit_form->parent);
+ $mform->addElement('hidden', 'name', $edit_form->name);
+ $mform->addElement('hidden', 'code', $edit_form->code);
+ $mform->addElement('hidden', 'description', $edit_form->description);
+ $mform->addElement('hidden', 'enabled', $edit_form->enabled);
+ $mform->addElement('hidden', 'op', $edit_form->op);
+ $mform->addElement('hidden', 'type', $edit_form->type);
+ $mform->addElement('hidden', 'category', $edit_form->category);
+ $mform->addElement('hidden', 'savenow', 1);
+
+ if($can_save)
+ {
+ if($edit_form->op == 'edit')
+ {
+ $this->add_action_buttons(true,get_string('faiscategoryadmin_report_submit', 'report_fitandproper'));
+ }else
+ {
+ $this->add_action_buttons(true,get_string('faiscategoryadmin_report_submit_delete', 'report_fitandproper'));
+ }
+ }else
+ {
+ $mform->addElement('html', ''.get_string('faiscategoryadmin_report_cannotdelete', 'report_fitandproper').'
');
+
+ $buttonarray=array();
+ $buttonarray[] = &$mform->createElement('cancel');
+ $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
+ $mform->closeHeaderBefore('buttonar');
+ }
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/faiscategorylinks.php b/admin/report/fitandproper/faiscategorylinks.php
new file mode 100644
index 00000000000..251de7e85ad
--- /dev/null
+++ b/admin/report/fitandproper/faiscategorylinks.php
@@ -0,0 +1,240 @@
+op == 'delete')
+ {
+ $form_data->name = $edit_category->name;
+ }
+
+ if($form_data->type == 'top')
+ {
+ $sub = $DB->get_records('fais_sub_category',array('fais_category_id'=>$form_data->category,'deleted'=>0));
+
+ $cpd_activities = array();
+ $qualifications = array();
+ $re_levels = array();
+
+ foreach($sub as $s)
+ {
+ //check links for the sub category
+ $cpd_activities += check_cpd_activities_links($s->id);
+ $re_levels += check_relevels_links($s->id);
+ }
+
+ //get categories
+ $qualifications += check_qualifications_links($form_data->category);
+
+ display_links_table($edit_category,$cpd_activities,$qualifications,$re_levels,$sub);
+
+ //check if they are trying to move a top category to a sub category
+ if((isset($form_data->parent) && $form_data->parent > 0) || $form_data->op == 'delete')
+ {
+ if(count($sub) > 0 || count($cpd_activities) > 0 || count($qualifications) > 0 || count($re_levels) > 0)
+ {
+ $can_save = false;
+ }else
+ {
+ $can_save = true;
+ }
+ }else
+ {
+ $can_save = true;
+ }
+
+ $form = new faiscategoryadmin_links_form(null,array('edit_form'=>$form_data,'can_save'=>$can_save));
+
+ if($data = $form->get_data())
+ {
+ }else
+ {
+ $form->display();
+ }
+ }else
+ {
+ $cpd_activities = array();
+ $qualifications = array();
+ $re_levels = array();
+
+ //check links for the sub category
+ $cpd_activities = check_cpd_activities_links($edit_category->id);
+ //$qualifications = check_qualifications_links($edit_category->id);
+ $re_levels = check_relevels_links($edit_category->id);
+
+ display_links_table($edit_category,$cpd_activities,$qualifications,$re_levels);
+
+ //check if they are trying to move a sub category to a top category
+ if((isset($form_data->parent) && $form_data->parent == 0) || $form_data->op == 'delete')
+ {
+ if(count($cpd_activities) > 0 || count($qualifications) > 0 || count($re_levels) > 0)
+ {
+ $can_save = false;
+ }else
+ {
+ $can_save = true;
+ }
+ }else
+ {
+ $can_save = true;
+ }
+
+ $form = new faiscategoryadmin_links_form(null,array('edit_form'=>$form_data,'can_save'=>$can_save));
+
+ if($data = $form->get_data())
+ {
+ }else
+ {
+ $form->display();
+ }
+ }
+}
+
+/**
+ * Display the links table
+ * @param object $category The FAIS category
+ * @param array Array of CPD Activities
+ * @param array Array of Qualifications
+ * @param array Array of RE Levels
+ * @param array Array of Sub categories
+ */
+function display_links_table($category,$cpd_activities,$qualifications,$re_levels,$sub_categories = null)
+{
+ echo '';
+ if(isset($sub_categories))
+ {
+ echo '
';
+ echo ''.get_string('faiscategoryadmin_report_subcategory_title', 'report_fitandproper').' '.$category->name.':'.' ';
+
+ if($sub_categories)
+ {
+ foreach($sub_categories as $s)
+ {
+ echo ''.$s->name.' ';
+ }
+ }else
+ {
+ echo ''.get_string('faiscategoryadmin_report_no_subcategory', 'report_fitandproper').' ';
+ }
+ echo '
';
+ }
+
+ //display linked cpd activities
+ echo '
';
+ echo ''.get_string('faiscategoryadmin_report_cpdactivity_title', 'report_fitandproper').' '.$category->name.':'.' '.get_string('faiscategoryadmin_report_users', 'report_fitandproper').' ';
+
+ if($cpd_activities)
+ {
+ foreach($cpd_activities as $c)
+ {
+ echo ''.$c->name.' ('.$c->code.') '.get_linked_count('cpd_activity',$c->id).' ';
+ }
+ }else
+ {
+ echo ''.get_string('faiscategoryadmin_report_no_cpdactivity', 'report_fitandproper').' ';
+ }
+ echo '
';
+
+ //display linked qualifications
+ echo '
';
+ echo ''.get_string('faiscategoryadmin_report_qualifications_title', 'report_fitandproper').' '.$category->name.':'.' '.get_string('faiscategoryadmin_report_users', 'report_fitandproper').' ';
+
+ if($qualifications)
+ {
+ foreach($qualifications as $q)
+ {
+ echo ''.$q->qualification_number.' ('.$q->title.') '.get_linked_count('qualification',$q->id).' ';
+ }
+ }else
+ {
+ echo ''.get_string('faiscategoryadmin_report_no_qualification', 'report_fitandproper').' ';
+ }
+ echo '
';
+
+ //display linked re_levels
+ echo '
';
+ echo ''.get_string('faiscategoryadmin_report_relevels_title', 'report_fitandproper').' '.$category->name.':'.' '.get_string('faiscategoryadmin_report_reexams', 'report_fitandproper').' ';
+ if($re_levels)
+ {
+ foreach($re_levels as $r)
+ {
+ echo ''.$r->name.' '.get_linked_count('re_level',$r->id).' ';
+ }
+ }else
+ {
+ echo ''.get_string('faiscategoryadmin_report_no_relevel', 'report_fitandproper').' ';
+ }
+ echo '
';
+
+ echo '
';
+}
+
+/**
+ * Get a list of CPD Activities that links to a FAIS sub category
+ * @param integer $id The id of the FAIS sub category
+ * @return array Array of CPD Activities
+ */
+function check_cpd_activities_links($id)
+{
+ global $DB;
+
+ $records = $DB->get_records_sql('SELECT c.* FROM {cpd_activity_fais_sub_cat} cs INNER JOIN {cpd_activity} c ON (cs.cpd_activity_id = c.id) WHERE cs.fais_sub_category_id = ? and c.deleted = ?',array($id,0));
+
+ return $records;
+}
+
+/**
+ * Get a list of Qualifications that links to a FAIS sub category
+ * @param integer $id The id of the FAIS sub category
+ * @return array Array of Qualifications
+ */
+function check_qualifications_links($id)
+{
+ global $DB;
+
+ $records = $DB->get_records_sql('SELECT q.* FROM {qualification} q INNER JOIN {fais_category} fc ON (q.fais_category_id = fc.id) WHERE fc.id = ? and q.deleted = ?',array($id,0));
+
+ return $records;
+}
+
+/**
+ * Get a list of RE Levels that links to a FAIS sub category
+ * @param integer $id The id of the FAIS sub category
+ * @return array Array of RE Levels
+ */
+function check_relevels_links($id)
+{
+ global $DB;
+
+ $records = $DB->get_records_sql('SELECT r.* FROM {re_level_fais_sub_cat} rs INNER JOIN {re_level} r ON (rs.re_level_id = r.id) WHERE rs.fais_sub_category_id = ? and r.deleted = ?',array($id,0));
+
+ return $records;
+}
+
+/**
+ * Get total number of users/exams linked to a CPD Activity/Qualification/RE Level
+ * @param string $type The type of link cpd_activity/qualification/re_level
+ * @param integer $id The id of the CPD Activity/Qualification/RE Level
+ * @return integer The total count of linked types
+ */
+function get_linked_count($type,$id)
+{
+ global $DB;
+
+ if($type == 're_level')
+ {
+ $users = $DB->get_record_sql('SELECT COUNT(id) as total FROM {re_exam} WHERE re_level_id = ? AND deleted = 0',array($id));
+ }else
+ {
+ $users = $DB->get_record_sql('SELECT COUNT(id) as total FROM {user_'.$type.'} WHERE '.$type.'_id = ? AND deleted = 0',array($id));
+ }
+
+ return $users->total;
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/institutionadmin.php b/admin/report/fitandproper/institutionadmin.php
new file mode 100644
index 00000000000..e99e5ae09d2
--- /dev/null
+++ b/admin/report/fitandproper/institutionadmin.php
@@ -0,0 +1,358 @@
+libdir.'/adminlib.php');
+//require_once('faiscategorylinks.php');
+require_once('institutionadmin_edit_form.php');
+require_once('institutionadmin_links_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewinstitutions', get_context_instance(CONTEXT_SYSTEM));
+
+$filter_code = optional_param('filter_code', null,PARAM_INTEGER);
+$filter_name = optional_param('filter_name', null,PARAM_INTEGER);
+$filter_code_text = optional_param('filter_code_text', null,PARAM_TEXT);
+$filter_name_text = optional_param('filter_name_text', null,PARAM_TEXT);
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+$step = optional_param('step', null,PARAM_INTEGER);
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/institutionadmin.php";
+
+// Print the header.
+admin_externalpage_setup('institutionadmin');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('institutionadmin_heading', 'report_fitandproper'));
+
+/*
+ * Check if user requested an add or edit institution
+ */
+$display = true;
+if($op == 'add' || $op == 'edit')
+{
+ $edit_form = new institutionadmin_edit_form(null,array('op'=>$op,'id'=>$id));
+ $data = $edit_form->get_data();
+
+ if($edit_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($data || $step == 2)
+ {
+ /*
+ * Check if user is doing an edit and display the links report
+ */
+ if($op == 'edit')
+ {
+ $links_form = new institutionadmin_links_form(null,array('edit_form'=>$data));
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($ldata = $links_form->get_data())
+ {
+ //edit
+ //create institution object
+ $record = new stdClass();
+ if($ldata->id != null && $ldata->id > 0)
+ {
+ $record->id = $ldata->id;
+ }
+ $record->name = $ldata->name;
+ $record->code = $ldata->code;
+ $record->enabled = (isset($ldata->enabled)) ? (int)$ldata->enabled : 0;
+ $record->timemodified = time();
+ $DB->update_record('institution', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'Institution', ": Edit", "report/fitandproper/institutionadmin.php",$record->name);
+ redirect($url);
+ }else
+ {
+ display_institution_links($data->id);
+
+ $links_form->display();
+ }
+ }
+
+ /*
+ * Add a new institution to the database
+ */
+ if($op == 'add')
+ {
+ //save
+ //create institution object
+ $record = new stdClass();
+ if($data->id != null && $data->id > 0)
+ {
+ $record->id = $data->id;
+ }
+ $record->name = $data->name;
+ $record->code = $data->code;
+ $record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->timecreated = time();
+ $DB->insert_record('institution', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'Institution', ": Add", "report/fitandproper/institutionadmin.php",$record->name);
+
+ redirect($url);
+ }
+ }else
+ {
+ $edit_form->display();
+ }
+ $display = false;
+}
+elseif($op == 'delete')
+{
+ /*
+ * Handle the deletion of institutions
+ */
+ require_capability('report/fitandproper:deleteinstitutions', get_context_instance(CONTEXT_SYSTEM));
+
+ $data = $DB->get_record('institution',array('id'=>$id,'deleted'=>0));
+
+ $data->op = 'delete';
+ $links_form = new institutionadmin_links_form(null,array('edit_form'=>$data));
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($ldata = $links_form->get_data())
+ {
+ /*
+ * Do the deletion and institution replacements on linked CPD activities and Qualifications
+ */
+ if($ldata->replace_institution > 0)
+ {
+ $DB->set_field('user_cpd_activity', 'institution_id', $ldata->replace_institution, array('institution_id'=>$ldata->id));
+ $DB->set_field('user_qualification', 'institution_id', $ldata->replace_institution, array('institution_id'=>$ldata->id));
+ }else
+ {
+ $DB->set_field('user_cpd_activity', 'deleted', 1, array('institution_id'=>$ldata->id));
+ $DB->set_field('user_qualification', 'deleted', 1, array('institution_id'=>$ldata->id));
+ }
+ $record = new stdClass();
+ $record->id = $ldata->id;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('institution', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'Institution', ": Delete", "report/fitandproper/institutionadmin.php",$ldata->name);
+
+ redirect($url);
+ }else
+ {
+ display_institution_links($data->id);
+ $links_form->display();
+ }
+ $display = false;
+}
+//echo $OUTPUT->notification('test');
+
+if($display)
+{
+ /*
+ * Display filter
+ */
+
+ $filteroptions = array(
+ 1=>'contains',
+ 2=>'doesn\'t contain',
+ 3=>'is equal to',
+ 4=>'starts with',
+ 5=>'ends with',
+ 6=>'is empty');
+ echo $OUTPUT->box_start('filterlist');
+ echo '';
+ echo ''.get_string('institutionadmin_filterhead', 'report_fitandproper').' ';
+ echo '';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+ /*
+ * Get list of institutions from database and apply filters if neccesary
+ */
+ if($filter_code_text != null || $filter_name_text != null || $filter_code == 6 || $filter_name == 6)
+ {
+ $where= '';
+ $params = array();
+ if($filter_code_text != null || $filter_code == 6)
+ {
+ switch($filter_code)
+ {
+ case 1 : $where = 'code LIKE ?';
+ $params[] = '%'.$filter_code_text.'%';
+ break;
+ case 2 : $where = 'code NOT LIKE ?';
+ $params[] = '%'.$filter_code_text.'%';
+ break;
+ case 3 : $where = 'code = ?';
+ $params[] = $filter_code_text;
+ break;
+ case 4 : $where = 'code LIKE ?';
+ $params[] = $filter_code_text.'%';
+ break;
+ case 5 : $where = 'code LIKE ?';
+ $params[] = '%'.$filter_code_text;
+ break;
+ case 6 : $where = 'code IS NULL OR code = ""';
+ break;
+ }
+ }
+ if($filter_name_text != null || $filter_name == 6)
+ {
+ if($filter_code_text != null) $where .= ' AND ';
+ switch($filter_name)
+ {
+ case 1 : $where .= 'name LIKE ?';
+ $params[] = '%'.$filter_name_text.'%';
+ break;
+ case 2 : $where .= 'name NOT LIKE ?';
+ $params[] = '%'.$filter_name_text.'%';
+ break;
+ case 3 : $where .= 'name = ?';
+ $params[] = $filter_name_text;
+ break;
+ case 4 : $where .= 'name LIKE ?';
+ $params[] = $filter_name_text.'%';
+ break;
+ case 5 : $where .= 'name LIKE ?';
+ $params[] = '%'.$filter_name_text;
+ break;
+ case 6 : $where .= 'name IS NULL OR code = ""';
+ break;
+ }
+ }
+ $where .= ' AND deleted = 0';
+ $institutions = $DB->get_records_select('institution',$where,$params,'name');
+ }
+ else
+ {
+ //no filter selected so get all records
+ $institutions = $DB->get_records('institution',array('deleted'=>0),'name');
+ }
+
+ /*
+ * Display intitions list table
+ */
+ echo $OUTPUT->box_start('institutionlist');
+ echo ''.get_string('institutionadmin_addnew', 'report_fitandproper').'
';
+
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('institutionadmin_tableheadcode', 'report_fitandproper'),get_string('institutionadmin_tableheadname', 'report_fitandproper'),'','');
+
+ $r = array();
+
+ if(count($institutions) > 0)
+ {
+ foreach($institutions as $i)
+ {
+ $edit = html_writer::link($url.'?op=edit&id='.$i->id,get_string('institutionadmin_tableedit', 'report_fitandproper'));
+ $delete = html_writer::link($url.'?op=delete&id='.$i->id,get_string('institutionadmin_tabledelete', 'report_fitandproper'));
+ $row = new html_table_row(array($i->code,$i->name,$edit,$delete));
+ if($i->enabled == 0) $row->attributes = array('class'=>'faiscategorydisabled');
+ $table->data[] = $row;
+ //$table->data[] = array($i->code,$i->name,$edit,$delete);
+ }
+ }
+ else
+ {
+ $empty = new html_table_cell(get_string('institutionadmin_tablenorows', 'report_fitandproper'));
+ $empty->colspan = '5';
+ $row = new html_table_row(array($empty));
+ $table->data[] = $row;
+
+ }
+ echo html_writer::table($table);
+
+ echo ''.get_string('institutionadmin_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+// Footer.
+echo $OUTPUT->footer();
+
+/**
+ * Function to display a report of all the users linked to a institution
+ * @param integer ID of the institution being edited or deleted
+ */
+function display_institution_links($institution_id)
+{
+ global $DB;
+
+ /*
+ * Get the current institution
+ */
+ $intitution = $DB->get_record('institution',array('id'=>$institution_id));
+
+ /*
+ * Get all qualifications
+ */
+ $qualifications = $DB->get_records_sql('SELECT moodle_user_id,COUNT(id) as total FROM {user_qualification} WHERE institution_id = ? AND deleted = 0 GROUP BY moodle_user_id',array($institution_id));
+
+ /*
+ * Get all cpd activities
+ */
+ $activities = $DB->get_records_sql('SELECT moodle_user_id,COUNT(id) as total FROM {user_cpd_activity} WHERE institution_id = ? AND deleted = 0 GROUP BY moodle_user_id',array($institution_id));
+
+ /*
+ * Put all the qualifications and activities in one array for processing
+ */
+ $links = array();
+ foreach($qualifications as $q)
+ {
+ @$links[$q->moodle_user_id]['qualifications'] = $links[$q->moodle_user_id]['qualifications'] + $q->total;
+ }
+
+ foreach($activities as $a)
+ {
+ @$links[$a->moodle_user_id]['activities'] = $links[$a->moodle_user_id]['activities'] + $a->total;
+ }
+
+ /*
+ * Display the table
+ */
+ echo 'Users currently linked to '.$intitution->code.' ('.$intitution->name.') ';
+ echo '';
+ echo ''.get_string('institutionadmin_report_user_title', 'report_fitandproper').' '.get_string('institutionadmin_report_quali_title', 'report_fitandproper').' '.get_string('institutionadmin_report_cpd_title', 'report_fitandproper').' ';
+
+ if($links)
+ {
+ foreach($links as $user=>$l)
+ {
+ //get user name
+ $username = $DB->get_record('user',array('id'=>$user),'firstname,lastname');
+
+ $q = (isset($l['qualifications'])) ? $l['qualifications'] : 0;
+ $a = (isset($l['activities'])) ? $l['activities'] : 0;
+ echo ''.$username->firstname.' '.$username->lastname.' '.$q.' '.$a.' ';
+ }
+ }else
+ {
+ echo ''.get_string('faiscategoryadmin_report_no_users', 'report_fitandproper').' ';
+ }
+
+ echo '
';
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/institutionadmin_edit_form.php b/admin/report/fitandproper/institutionadmin_edit_form.php
new file mode 100644
index 00000000000..dbab4bcb7e0
--- /dev/null
+++ b/admin/report/fitandproper/institutionadmin_edit_form.php
@@ -0,0 +1,80 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the Institutions add/edit form
+ */
+class institutionadmin_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+
+ /*
+ * if this is a edit form get the institution data for edit
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $data = $DB->get_record('institution',array('id'=>$id,'deleted'=>0));
+ }
+
+ $header = ($op == 'edit') ? 'Edit' : 'Add';
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('text', 'code', get_string('institution_code', 'report_fitandproper'));
+ $mform->addRule('code', null, 'required', null, 'client');
+ $mform->addRule('code', null, 'maxlength', 255, 'client');
+ $mform->addRule('code', get_string('institution_codeformat', 'report_fitandproper'), 'regex', "/^[a-zA-Z0-9_]+$/", 'client');
+ $mform->addElement('text', 'name', get_string('institution_name', 'report_fitandproper'));
+ $mform->addRule('name', null, 'required', null, 'client');
+ $mform->addRule('name', null, 'maxlength', 255, 'client');
+ $mform->addRule('name', get_string('institution_nameformat', 'report_fitandproper'), 'regex', "/^[a-zA-Z0-9\s]+$/", 'client');
+ $mform->addElement('checkbox', 'enabled', get_string('enabled', 'report_fitandproper'));
+
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'id');
+
+ if($op == 'edit')
+ {
+ $mform->setDefault('id', $id);
+ $mform->setDefault('name', $data->name);
+ $mform->setDefault('code', $data->code);
+ $mform->setDefault('enabled', $data->enabled);
+ }else
+ {
+ $mform->setDefault('enabled', 1);
+ }
+
+ $this->add_action_buttons(true,get_string('institution_submit', 'report_fitandproper'));
+
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+ //check for duplicate code
+ $check = $DB->count_records_select('institution','deleted = 0 and code = ? and id != ?',array($data['code'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['code'] = get_string('institution_submit_duplicate_code', 'report_fitandproper');
+ }
+
+ //check for duplicate name
+ $check = $DB->count_records_select('institution','deleted = 0 and name = ? and id != ?',array($data['name'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['name'] = get_string('institution_submit_duplicate_name', 'report_fitandproper');
+ }
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/institutionadmin_links_form.php b/admin/report/fitandproper/institutionadmin_links_form.php
new file mode 100644
index 00000000000..7f7d83c7bc0
--- /dev/null
+++ b/admin/report/fitandproper/institutionadmin_links_form.php
@@ -0,0 +1,49 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the Intitutions edit links report form
+ */
+class institutionadmin_links_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $edit_form = $this->_customdata['edit_form'];
+ //$can_save = $this->_customdata['can_save'];
+
+ $mform->addElement('hidden', 'id', $edit_form->id);
+ $mform->addElement('hidden', 'name', $edit_form->name);
+ $mform->addElement('hidden', 'code', $edit_form->code);
+ $mform->addElement('hidden', 'enabled', $edit_form->enabled);
+ $mform->addElement('hidden', 'op', $edit_form->op);
+ $mform->addElement('hidden', 'step', 2);
+
+ if($edit_form->op == 'edit')
+ {
+ $this->add_action_buttons(true,get_string('institutionadmin_report_submit', 'report_fitandproper'));
+ }elseif($edit_form->op == 'delete')
+ {
+ $mform->addElement('html', ''.get_string('institutionadmin_report_deleteinfo', 'report_fitandproper').'
');
+
+ /*
+ * Display select box for what to do with linked institutions
+ */
+ $institutions = $DB->get_records('institution',array('deleted'=>0,'enabled'=>1),'name');
+ $institution_list = array('0'=>'None, all linked CPD Activities and Qualifications should be deleted');
+ foreach($institutions as $i)
+ {
+ $institution_list[$i->id] = $i->name;
+ }
+ unset($institution_list[$edit_form->id]);
+ $mform->addElement('select','replace_institution','',$institution_list);
+
+ $this->add_action_buttons(true,get_string('institutionadmin_report_submit_delete', 'report_fitandproper'));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/lang/en/report_fitandproper.php b/admin/report/fitandproper/lang/en/report_fitandproper.php
new file mode 100644
index 00000000000..99f212f0924
--- /dev/null
+++ b/admin/report/fitandproper/lang/en/report_fitandproper.php
@@ -0,0 +1,305 @@
+get_file($context->id, 'report_fitandproper', $filearea, $args[0], '/', $args[1]);
+
+ send_stored_file($file, 0, 0, true);
+}
+
+?>
\ No newline at end of file
diff --git a/admin/report/fitandproper/module.js b/admin/report/fitandproper/module.js
new file mode 100644
index 00000000000..8bef5bf9117
--- /dev/null
+++ b/admin/report/fitandproper/module.js
@@ -0,0 +1,50 @@
+M.report_fitandproper = {
+ select: null,
+ subselect: null,
+
+ init: function(Y) {
+ var context = M.report_fitandproper;
+ context.select = document.getElementById('id_category');
+ context.subselect = document.getElementById('id_subcategory');
+
+ Y.on('change', context.getcats, context.select);
+ },
+
+ getcats: function(Y) {
+ var context = M.report_fitandproper;
+
+ var handlers = {
+ success: success,
+ failure: failure
+ };
+ function success( t ) {
+ YUI().use('json-parse', function (Y) {
+ var data = Y.JSON.parse(t.responseText);
+
+ if(data.count > 0)
+ {
+ context.subselect.options.length = 0;
+ for(var key in data.categories)
+ {
+ context.subselect.options[context.subselect.options.length] = new Option(data.categories[key].name,data.categories[key].id,false,false);
+ }
+ }else
+ {
+ context.subselect.options.length = 0;
+ context.subselect.options[0] = new Option('This category has no sub categories',0,false,false);
+ }
+ });
+ document.getElementById('id_submitbutton').disabled = false;
+ }
+ function failure( t ) {
+ alert( 'There was an error: ' + t.statusText);
+ document.getElementById('id_submitbutton').disabled = false;
+ }
+
+ if(context.select.value != 0)
+ {
+ document.getElementById('id_submitbutton').disabled = true;
+ call = YAHOO.util.Connect.asyncRequest('GET', 'cpdactivityadmin_ajax.php?cid='+context.select.value, handlers);
+ }
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/module_cpdactivitymanager.js b/admin/report/fitandproper/module_cpdactivitymanager.js
new file mode 100644
index 00000000000..8021b83ca1a
--- /dev/null
+++ b/admin/report/fitandproper/module_cpdactivitymanager.js
@@ -0,0 +1,50 @@
+M.report_fitandproper = {
+ select: null,
+ level: null,
+ category_select: null,
+ subcategory_select: null,
+
+ init: function(Y,t_qcodes) {
+ var context = M.report_fitandproper;
+ context.select = document.getElementById('id_activity');
+ context.level = document.getElementById('id_hours');
+ context.category_select = document.getElementById('id_category');
+ context.subcategory_select = document.getElementById('id_subcategory');
+
+ Y.on('change', context.selectdata, context.select);
+ },
+
+ selectdata: function(Y) {
+ var context = M.report_fitandproper;
+
+ var handlers = {
+ success: success,
+ failure: failure
+ };
+ function success( t ) {
+ YUI().use('json-parse', function (Y) {
+ var data = Y.JSON.parse(t.responseText);
+
+ context.level.value = data.hours;
+ if(data.count > 0)
+ {
+ context.category_select.value = data.category
+
+ context.subcategory_select.options.length = 0;
+ for(var key in data.subcategories)
+ {
+ context.subcategory_select.options[context.subcategory_select.options.length] = new Option(data.subcategories[key],key,false,false);
+ }
+ }
+ });
+ }
+ function failure( t ) {
+ alert( 'There was an error: ' + t.statusText);
+ }
+
+ if(context.select.value != 0)
+ {
+ call = YAHOO.util.Connect.asyncRequest('GET', 'cpdactivitymanager_ajax.php?aid='+context.select.value, handlers);
+ }
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/module_qualificationmanager.js b/admin/report/fitandproper/module_qualificationmanager.js
new file mode 100644
index 00000000000..9658bef3f99
--- /dev/null
+++ b/admin/report/fitandproper/module_qualificationmanager.js
@@ -0,0 +1,32 @@
+M.report_fitandproper = {
+ select: null,
+ level: null,
+ qcodes: null,
+
+ init: function(Y,t_qcodes) {
+ var context = M.report_fitandproper;
+ context.select = document.getElementById('id_qualification');
+ context.level = document.getElementById('id_nqf');
+ context.qcodes = Y.JSON.parse(t_qcodes);
+ Y.on('change', context.selectlevel, context.select);
+ },
+
+ selectlevel: function(Y) {
+ var context = M.report_fitandproper;
+
+ scode = context.select.value;
+ if(scode == 0)
+ {
+ context.level.value = '';
+ }else
+ {
+ for(var key in context.qcodes)
+ {
+ if(key == scode)
+ {
+ context.level.value = context.qcodes[key];
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/module_reexamresultsmanager.js b/admin/report/fitandproper/module_reexamresultsmanager.js
new file mode 100644
index 00000000000..7323dd1e1e8
--- /dev/null
+++ b/admin/report/fitandproper/module_reexamresultsmanager.js
@@ -0,0 +1,51 @@
+M.report_fitandproper = {
+ level: null,
+ exam_select: null,
+
+ init: function(Y,t_qcodes) {
+ var context = M.report_fitandproper;
+ context.level = document.getElementById('id_level');
+ context.exam_select = document.getElementById('id_re_exam');
+
+ Y.on('change', context.selectdata, context.level);
+ },
+
+ selectdata: function(Y) {
+ var context = M.report_fitandproper;
+
+ var handlers = {
+ success: success,
+ failure: failure
+ };
+
+ //add exams from level to exams list
+ function success( t ) {
+ YUI().use('json-parse', function (Y) {
+ var data = Y.JSON.parse(t.responseText);
+
+ if(data.count > 0)
+ {
+
+ context.exam_select.options.length = 0;
+ context.exam_select.options[context.exam_select.options.length] = new Option("Select Re Exam",0,false,false);
+ for(var key in data.exams)
+ {
+ context.exam_select.options[context.exam_select.options.length] = new Option(data.exams[key],key,false,false);
+ }
+ }
+ });
+ }
+ function failure( t ) {
+ alert( 'There was an error: ' + t.statusText);
+ }
+
+ //call ajax for options or add default option to exams list depends on selected exam
+ if(context.level.value != 0)
+ {
+ call = YAHOO.util.Connect.asyncRequest('GET', 'reexamresultsmanager_ajax.php?lid='+context.level.value, handlers);
+ } else {
+ context.exam_select.options.length = 0;
+ context.exam_select.options[context.exam_select.options.length] = new Option("Select Re Level first",0,false,false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/pix/add.gif b/admin/report/fitandproper/pix/add.gif
new file mode 100644
index 00000000000..f92785d2f72
Binary files /dev/null and b/admin/report/fitandproper/pix/add.gif differ
diff --git a/admin/report/fitandproper/pix/delete.gif b/admin/report/fitandproper/pix/delete.gif
new file mode 100644
index 00000000000..d17f867e45f
Binary files /dev/null and b/admin/report/fitandproper/pix/delete.gif differ
diff --git a/admin/report/fitandproper/pix/edit.gif b/admin/report/fitandproper/pix/edit.gif
new file mode 100644
index 00000000000..f32a84568d9
Binary files /dev/null and b/admin/report/fitandproper/pix/edit.gif differ
diff --git a/admin/report/fitandproper/qualificationadmin.php b/admin/report/fitandproper/qualificationadmin.php
new file mode 100644
index 00000000000..ba8dc4e53c5
--- /dev/null
+++ b/admin/report/fitandproper/qualificationadmin.php
@@ -0,0 +1,676 @@
+libdir.'/adminlib.php');
+require_once($CFG->libdir.'/csvlib.class.php');
+require_once 'qualificationadmin_upload_form.php';
+require_once 'qualificationadmin_report_form.php';
+require_once('qualificationadmin_filter_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+$iid = optional_param('iid', null, PARAM_INT);
+$cat_id = optional_param('cat_id', null, PARAM_INT);
+
+require_login();
+
+require_capability('report/fitandproper:viewqualifications', get_context_instance(CONTEXT_SYSTEM));
+
+$filter_code = optional_param('filter_code', null,PARAM_INTEGER);
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationadmin.php";
+
+// Print the header.
+admin_externalpage_setup('qualificationadmin');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('qualificationadmin_heading', 'report_fitandproper'));
+
+//$table->attributes = array('align'=>'center');
+$tablehead = array(get_string('qualificationadmin_tableheadno', 'report_fitandproper'),
+ get_string('qualificationadmin_tableheadtitle', 'report_fitandproper'),
+ get_string('qualificationadmin_tableheadid', 'report_fitandproper'),
+ get_string('qualificationadmin_tableheadlevel', 'report_fitandproper'),
+ get_string('qualificationadmin_tableheadcredits', 'report_fitandproper'),
+ '1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','ki');
+//var_dump($CFG);
+/*
+ * Handle the CSV file upload event
+ */
+$upload_form = new qualificationadmin_upload_form(null);
+
+$show_report = false;
+if($upload_form->is_cancelled())
+{
+ redirect($url);
+}
+elseif($data = $upload_form->get_data())
+{
+ $iid = csv_import_reader::get_new_iid('qualification');
+ $cir = new csv_import_reader($iid, 'qualification');
+
+ $content = $upload_form->get_file_content('csvfile');
+ $readcount = $cir->load_csv_content($content, 'UTF-8', 'comma');
+
+ $cir->close();
+ if($cir->get_error() != null)
+ {
+ print_error('csvloaderror', '', $url);
+ }else
+ {
+ /*
+ * If there is no error in the CSV file, display import report
+ */
+ $report = get_qualifications_import_report($iid,$cir,$data->category);
+
+ display_qualifications_import_report($report,$tablehead,$data->category,$readcount);
+
+ $links_form = new qualificationadmin_report_form(null,array('iid'=>$iid,'cat_id'=>$data->category));
+
+ $links_form->display();
+ }
+ $show_report = true;
+}
+
+if($iid > 0 && $show_report == false)
+{
+ $links_form = new qualificationadmin_report_form(null);
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }elseif($data = $links_form->get_data())
+ {
+ /*
+ * Report accepted and now process the import
+ */
+ require_capability('report/fitandproper:deletequalifications', get_context_instance(CONTEXT_SYSTEM));
+
+ $cir = new csv_import_reader($iid, 'qualification');
+ $report = get_qualifications_import_report($iid,$cir,$cat_id);
+
+ do_qualifications_import($report,$cat_id);
+ $cir->close();
+ $cir->cleanup();
+
+ // Log.
+ add_to_log(SITEID, 'Qualification', ": Upload", "report/fitandproper/qualificationadmin.php",'Qualifications');
+
+ redirect($url);
+ }
+}
+
+if($iid == null)
+{
+ /*
+ * Display the CSV upload form
+ */
+ $upload_form = new qualificationadmin_upload_form(null);
+
+ $upload_form->display();
+
+ /*
+ * Display filter
+ */
+ $filter_form = new qualificationadmin_filter_form(null,array());
+ echo $OUTPUT->box_start('filterlist');
+ echo '';
+ echo ''.get_string('qualificationadmin_filter_head', 'report_fitandproper').' ';
+ echo '';
+ $filter_form->display();
+ echo '
';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+
+ $where = 'deleted = ?';
+ $params = array(0=>0);
+ if($fdata = $filter_form->get_data()) {
+ if($fdata->qualification_id_text != "" || $fdata->qualification_id == 6) {
+ $where .= ' AND ';
+ switch ($fdata->qualification_id) {
+ case 1 : $where .= 'id_number LIKE ?';
+ $params[] = '%'.$fdata->qualification_id_text.'%';
+ break;
+ case 2 : $where .= 'id_number NOT LIKE ?';
+ $params[] = '%'.$fdata->qualification_id_text.'%';
+ break;
+ case 3 : $where .= 'id_number = ?';
+ $params[] = $fdata->qualification_id_text;
+ break;
+ case 4 : $where .= 'id_number LIKE ?';
+ $params[] = $fdata->qualification_id_text.'%';
+ break;
+ case 5 : $where .= 'id_number LIKE ?';
+ $params[] = '%'.$fdata->qualification_id_text;
+ break;
+ case 6 : $where .= "id_number IS NULL OR id_number = ''";
+ break;
+ }
+ }
+
+ if($fdata->qualification_name_text != "" || $fdata->qualification_name == 6) {
+ $where .= ' AND ';
+ switch ($fdata->qualification_name) {
+ case 1 : $where .= 'title LIKE ?';
+ $params[] = '%'.$fdata->qualification_name_text.'%';
+ break;
+ case 2 : $where .= 'title NOT LIKE ?';
+ $params[] = '%'.$fdata->qualification_name_text.'%';
+ break;
+ case 3 : $where .= 'title = ?';
+ $params[] = $fdata->qualification_name_text;
+ break;
+ case 4 : $where .= 'title LIKE ?';
+ $params[] = $fdata->qualification_name_text.'%';
+ break;
+ case 5 : $where .= 'title LIKE ?';
+ $params[] = '%'.$fdata->qualification_name_text;
+ break;
+ case 6 : $where .= "title IS NULL OR title = ''";
+ break;
+ }
+ }
+
+ if($fdata->qualification_nqf_text != "") {
+ $where .= ' AND ';
+ $where .= 'qualification_level = ?';
+ $params[] = $fdata->qualification_nqf_text;
+ }
+
+ if($fdata->qualification_credits_text != "") {
+ $where .= ' AND ';
+ $where .= 'credits = ?';
+ $params[] = $fdata->qualification_credits_text;
+ }
+
+ }
+
+ $qualifications = $DB->get_records_sql("SELECT q.fais_category_id,c.name,COUNT(q.id) FROM {qualification} q INNER JOIN {fais_category} c ON (q.fais_category_id = c.id) WHERE q.deleted = 0 GROUP BY q.fais_category_id,c.name ORDER BY c.name");
+ /*
+ * Display qualifications list table
+ */
+ echo $OUTPUT->box_start('qualificationlist');
+
+ //$qualifications = $DB->get_records_sql('SELECT * FROM {qualification} WHERE deleted = 0 ORDER BY fais_category_id,title');
+
+ $category = 0;
+ $cat_total = 0;
+
+ if(count($qualifications) > 0)
+ {
+ foreach($qualifications as $q)
+ {
+ $where.= ' AND fais_category_id = ?';
+ $params[] = $q->fais_category_id;
+ $qual = $DB->get_records_select('qualification',$where, array_merge($params),'qualification_number');
+ echo ''.$q->name.' ('.count($qual).') ';
+
+ $table = new html_table();
+ $table->head = $tablehead;
+ foreach($qual as $ql)
+ {
+ $row = new html_table_row(array($ql->qualification_number,$ql->title,$ql->id_number,$ql->qualification_level,$ql->credits,
+ $ql->cat_1,$ql->cat_2,$ql->cat_3,$ql->cat_4,$ql->cat_5,$ql->cat_6,$ql->cat_7,$ql->cat_8,$ql->cat_9,$ql->cat_10,$ql->cat_11,$ql->cat_12,$ql->cat_13,$ql->cat_14,$ql->cat_15,$ql->cat_16,$ql->cat_17,$ql->cat_18,$ql->cat_19,$ql->cat_20,$ql->cat_ki));
+ if($ql->enabled == 0) $row->attributes = array('class'=>'disabled');
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+ /*
+ $table = new html_table();
+ foreach($qualifications as $q)
+ {
+ if($category != $q->fais_category_id)
+ {
+ if($category != 0)
+ {
+ //close table if we are at a new category
+ echo html_writer::table($table);
+ }
+
+ //get category name
+ $cat = $DB->get_record('fais_category',array('id'=>$q->fais_category_id));
+
+ echo ''.$cat->name.' ';
+
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ $category = $q->fais_category_id;
+ }
+
+ $row = new html_table_row(array($q->qualification_number,$q->title,$q->id_number,$q->qualification_level,$q->credits,
+ $q->cat_1,$q->cat_2,$q->cat_3,$q->cat_4,$q->cat_5,$q->cat_6,$q->cat_7,$q->cat_8,$q->cat_9,$q->cat_10,$q->cat_11,$q->cat_12,$q->cat_13,$q->cat_14,$q->cat_15,$q->cat_16,$q->cat_17,$q->cat_18,$q->cat_19,$q->cat_20,$q->cat_ki));
+ if($q->enabled == 0) $row->attributes = array('class'=>'disabled');
+ $table->data[] = $row;
+ }*/
+ }
+ else
+ {
+ $table = new html_table();
+ $table->head = array('');
+ $row = new html_table_row(array(get_string('qualificationadmin_tablenorows', 'report_fitandproper')));
+ $row->attributes = array('class'=>'10');
+ $table->data[] = $row;
+ }
+
+ //echo html_writer::table($table);
+
+ echo $OUTPUT->box_end();
+
+}
+
+// Footer.
+echo $OUTPUT->footer();
+
+/**
+ * Function to get a report of the qualifications imports
+ * @param integer $iid ID of the uploaded CSV file
+ * @param object $cir The CSV file import class
+ * @param integer $category The id of the selected category
+ * @return accociative array of the report
+ */
+function get_qualifications_import_report($iid,$cir,$category)
+{
+ global $DB;
+
+ $arr_q_ids = array();
+ $arr_add = array();
+ $arr_update = array();
+ $arr_delete = array();
+ $arr_unchange = array();
+ $arr_ignore = array();
+
+ //get list from database;
+ $qualifications = $DB->get_records('qualification',array('deleted'=>0,'fais_category_id'=>$category));
+
+ $cir->init();
+ while ($line = $cir->next())
+ {
+
+ //make sure cat_x is uppercase, and change '-' to space
+ for($x=5;$x<=25;$x++)
+ {
+ $line[$x] = strtoupper($line[$x]);
+ if(trim($line[$x]) == '-') $line[$x] = '';
+ }
+
+ if(!in_array($line[2],$arr_q_ids))
+ {
+
+ $arr_q_ids[] = $line[2];
+
+ //check if qualification is already in database
+ $in_db = false;
+ foreach($qualifications as $q)
+ {
+ if($line[2] == $q->id_number)
+ {
+ $line['db_id'] = $q->id;
+ $in_db = true;
+ $validate = validate_row($line);
+
+ if($validate === true)
+ {
+ //check if qualification is updated or changed
+ $unchange = true;
+
+ if($line[0] != $q->qualification_number) $unchange = false;
+ if($line[1] != $q->title) $unchange = false;
+ if($line[3] != $q->qualification_level) $unchange = false;
+ if($line[4] != $q->credits) $unchange = false;
+ if($line[5] != $q->cat_1) $unchange = false;
+ if($line[6] != $q->cat_2) $unchange = false;
+ if($line[7] != $q->cat_3) $unchange = false;
+ if($line[8] != $q->cat_4) $unchange = false;
+ if($line[9] != $q->cat_5) $unchange = false;
+ if($line[10] != $q->cat_6) $unchange = false;
+ if($line[11] != $q->cat_7) $unchange = false;
+ if($line[12] != $q->cat_8) $unchange = false;
+ if($line[13] != $q->cat_9) $unchange = false;
+ if($line[14] != $q->cat_10) $unchange = false;
+ if($line[15] != $q->cat_11) $unchange = false;
+ if($line[16] != $q->cat_12) $unchange = false;
+ if($line[17] != $q->cat_13) $unchange = false;
+ if($line[18] != $q->cat_14) $unchange = false;
+ if($line[19] != $q->cat_15) $unchange = false;
+ if($line[20] != $q->cat_16) $unchange = false;
+ if($line[21] != $q->cat_17) $unchange = false;
+ if($line[22] != $q->cat_18) $unchange = false;
+ if($line[23] != $q->cat_19) $unchange = false;
+ if($line[24] != $q->cat_20) $unchange = false;
+ if($line[25] != $q->cat_ki) $unchange = false;
+
+ if($unchange)
+ {
+ $arr_unchange[$line[2]] = $line;
+ }else
+ {
+ $arr_update[$line[2]] = array('u'=>$line,'c'=>$q);
+ }
+
+ }else
+ {
+
+ $arr_ignore[] = array('line'=>$line,'errors'=>$validate);
+ }
+ $q->in_csv = true;
+ }
+ }
+ //this is a new entry
+ if($in_db == false)
+ {
+ $validate = validate_row($line);
+ if($validate === true)
+ {
+ $arr_add[$line[2]] = $line;
+ }else
+ {
+ $arr_ignore[] = array('line'=>$line,'errors'=>$validate);
+ }
+ }
+ }else
+ {
+ /*
+ * there is a duplicate in the csv file
+ */
+ $arr_ignore[] = array('line'=>$line,'errors'=>array('Duplicate ID No'=>1));
+
+ //get the other duplicate one
+ foreach($arr_update as $i=>$data)
+ {
+ if($i == $line[2])
+ {
+ $arr_ignore[] = array('line'=>$data['u'],'errors'=>array('Duplicate ID No'=>1));
+ unset($arr_update[$line[2]]);
+ }
+ }
+ foreach($arr_unchange as $i=>$data)
+ {
+ if($i == $line[2])
+ {
+ $arr_ignore[] = array('line'=>$data,'errors'=>array('Duplicate ID No'=>1));
+ unset($arr_unchange[$line[2]]);
+ }
+ }
+ foreach($arr_add as $i=>$data)
+ {
+ if($i == $line[2])
+ {
+ $arr_ignore[] = array('line'=>$data,'errors'=>array('Duplicate ID No'=>1));
+ unset($arr_add[$line[2]]);
+ }
+ }
+ }
+ }
+
+ /*
+ * Check wich entries in the database to delete
+ */
+ foreach($qualifications as $q)
+ {
+ if(!isset($q->in_csv) || $q->in_csv == false)
+ {
+ $arr_delete[] = $q;
+ }
+ }
+
+ /*
+ * return an array of the report rows within their repective actions eg.add/update/delete/unchange/ingore
+ */
+ return array('add'=>$arr_add,'update'=>$arr_update,'delete'=>$arr_delete,'unchange'=>$arr_unchange,'ignore'=>$arr_ignore);
+}
+
+/**
+ * Function to validate a single row from the CSV file
+ * @param array The row array
+ * @return boolean True if it validates else an array of errors
+ */
+function validate_row($row)
+{
+ $errors = array();
+
+ if(!is_numeric($row[0])) $errors['Invalid No'] = 1;
+ if(!is_numeric($row[3])) $errors['Invalid Level'] = 1;
+ if(!is_numeric($row[4])) $errors['Invalid Credits'] = 1;
+
+ for($x=5;$x<=25;$x++)
+ {
+ if(strtoupper($row[$x]) == 'G' || strtoupper($row[$x]) == 'S' || strtoupper($row[$x]) == 'SP' || $row[$x] == '' || $row[$x] == '-')
+ {
+ //var_dump(strtoupper($row[$x]));
+ //return false;
+ }else
+ {
+ //var_dump(strtoupper($row[$x]));
+ $errors['Invalid Status Code'] = 1;
+ }
+ }
+
+ if(count($errors) == 0)
+ {
+ return true;
+ }else
+ {
+ return $errors;
+ }
+}
+
+/**
+ * Function to display the qualifications imports
+ * @param array The report in an array
+ */
+function display_qualifications_import_report($report,$tablehead,$cat_id,$count)
+{
+ global $DB;
+
+ $category = $DB->get_record('fais_category',array('id'=>$cat_id));
+
+ print ''.$category->name.' Qualifictaions processed: '.$count;
+ /*
+ * Display add
+ */
+ echo ''.get_string('qualificationadmin_report_add', 'report_fitandproper').': '.count($report['add']).' ';
+ if(count($report['add']) > 0)
+ {
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ foreach($report['add'] as $q)
+ {
+ $row = new html_table_row(array($q[0],$q[1],$q[2],$q[3],$q[4],
+ $q[5],$q[6],$q[7],$q[8],$q[9],$q[10],$q[11],$q[12],$q[13],$q[14],$q[15],$q[16],$q[17],$q[18],$q[19],$q[20],$q[21],$q[22],$q[23],$q[24],$q[25]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display update
+ */
+ echo ''.get_string('qualificationadmin_report_update', 'report_fitandproper').': '.count($report['update']).' ';
+ if(count($report['update']) > 0)
+ {
+ $table = new html_table();
+
+ $head = array('');
+ $head = array_merge($head,$tablehead);
+ $table->head = $head;
+
+ foreach($report['update'] as $q)
+ {
+ $row = new html_table_row(array(get_string('qualificationadmin_report_update_current', 'report_fitandproper'),$q['c']->qualification_number,$q['c']->title,$q['c']->id_number,$q['c']->qualification_level,$q['c']->credits,
+ $q['c']->cat_1,$q['c']->cat_2,$q['c']->cat_3,$q['c']->cat_4,$q['c']->cat_5,$q['c']->cat_6,$q['c']->cat_7,$q['c']->cat_8,$q['c']->cat_9,$q['c']->cat_10,$q['c']->cat_11,$q['c']->cat_12,$q['c']->cat_13,$q['c']->cat_14,$q['c']->cat_15,$q['c']->cat_16,$q['c']->cat_17,$q['c']->cat_18,$q['c']->cat_19,$q['c']->cat_20,$q['c']->cat_ki));
+ $table->data[] = $row;
+
+ $row = new html_table_row(array(get_string('qualificationadmin_report_update_update', 'report_fitandproper'),$q['u'][0],$q['u'][1],$q['u'][2],$q['u'][3],$q['u'][4],
+ $q['u'][5],$q['u'][6],$q['u'][7],$q['u'][8],$q['u'][9],$q['u'][10],$q['u'][11],$q['u'][12],$q['u'][13],$q['u'][14],$q['u'][15],$q['u'][16],$q['u'][17],$q['u'][18],$q['u'][19],$q['u'][20],$q['u'][21],$q['u'][22],$q['u'][23],$q['u'][24],$q['u'][25]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display delete
+ * delete is a class object
+ */
+ echo ''.get_string('qualificationadmin_report_delete', 'report_fitandproper').': '.count($report['delete']).' ';
+ if(count($report['delete']) > 0)
+ {
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ foreach($report['delete'] as $q)
+ {
+ $row = new html_table_row(array($q->qualification_number,$q->title,$q->id_number,$q->qualification_level,$q->credits,
+ $q->cat_1,$q->cat_2,$q->cat_3,$q->cat_4,$q->cat_5,$q->cat_6,$q->cat_7,$q->cat_8,$q->cat_9,$q->cat_10,$q->cat_11,$q->cat_12,$q->cat_13,$q->cat_14,$q->cat_15,$q->cat_16,$q->cat_17,$q->cat_18,$q->cat_19,$q->cat_20,$q->cat_ki));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display unchanged
+ */
+ echo ''.get_string('qualificationadmin_report_unchange', 'report_fitandproper').': '.count($report['unchange']).' ';
+ if(count($report['unchange']) > 0)
+ {
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ foreach($report['unchange'] as $q)
+ {
+ $row = new html_table_row(array($q[0],$q[1],$q[2],$q[3],$q[4],
+ $q[5],$q[6],$q[7],$q[8],$q[9],$q[10],$q[11],$q[12],$q[13],$q[14],$q[15],$q[16],$q[17],$q[18],$q[19],$q[20],$q[21],$q[22],$q[23],$q[24],$q[25]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+/*
+ * Display ignored
+ */
+ echo ''.get_string('qualificationadmin_report_ignore', 'report_fitandproper').': '.count($report['ignore']).' ';
+ if(count($report['ignore']) > 0)
+ {
+ $head = array(get_string('qualificationadmin_report_ignore_error', 'report_fitandproper'));
+ $head = array_merge($head,$tablehead);
+ $table = new html_table();
+ $table->head = $head;
+
+ foreach($report['ignore'] as $q)
+ {
+ $errors = '';
+
+ foreach($q['errors'] as $e=>$x)
+ {
+ $errors .= $e.',';
+ }
+ $errors = rtrim($errors,',');
+
+ $row = new html_table_row(array($errors,$q['line'][0],$q['line'][1],$q['line'][2],$q['line'][3],$q['line'][4],
+ $q['line'][5],$q['line'][6],$q['line'][7],$q['line'][8],$q['line'][9],$q['line'][10],$q['line'][11],$q['line'][12],$q['line'][13],$q['line'][14],$q['line'][15],$q['line'][16],$q['line'][17],$q['line'][18],$q['line'][19],$q['line'][20],$q['line'][21],$q['line'][22],$q['line'][23],$q['line'][24],$q['line'][25]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+}
+
+/**
+ * Function that does the actual import to database
+ * @param array The report data in an array
+ * @param integer The id of the selected category
+ */
+function do_qualifications_import($report,$cat_id)
+{
+ global $DB;
+
+ /*
+ * Proccess the added qualifications
+ */
+ foreach($report['add'] as $r)
+ {
+ $record = new stdClass();
+ $record->qualification_number = $r[0];
+ $record->title = $r[1];
+ $record->id_number = $r[2];
+ $record->qualification_level = $r[3];
+ $record->credits = $r[4];
+
+ $y=1;
+ for($x=5;$x<=24;$x++)
+ {
+ if($r[$x] == '-') $r[$x] = '';
+
+ $record->{"cat_$y"} = $r[$x];
+ $y++;
+ }
+ $record->cat_ki = $r[25];
+ $record->fais_category_id = $cat_id;
+ $record->enabled = 1;
+ $record->deleted = 0;
+ $record->timecreated = time();
+
+ $DB->insert_record('qualification',$record,false);
+ unset($record);
+ }
+
+ /*
+ * Proccess the updated qualifications
+ */
+ foreach($report['update'] as $r)
+ {
+ $record = new stdClass();
+ $record->qualification_number = $r['u'][0];
+ $record->title = $r['u'][1];
+ $record->id_number = $r['u'][2];
+ $record->qualification_level = $r['u'][3];
+ $record->credits = $r['u'][4];
+
+ $y=1;
+ for($x=5;$x<=24;$x++)
+ {
+ $record->{"cat_$y"} = $r['u'][$x];
+ $y++;
+ }
+ $record->cat_ki = $r['u'][25];
+ $record->fais_category_id = $cat_id;
+ $record->enabled = 1;
+ $record->deleted = 0;
+ $record->timecreated = time();
+
+ $DB->insert_record('qualification',$record,false);
+
+ //delete old record
+ $record = new stdClass();
+ $record->id = $r['u']['db_id'];
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('qualification',$record);
+ }
+
+ /*
+ * Proccess the deleted qualifications
+ */
+ foreach($report['delete'] as $r)
+ {
+ $record = new stdClass();
+ $record->id = $r->id;
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('qualification',$record);
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationadmin_filter_form.php b/admin/report/fitandproper/qualificationadmin_filter_form.php
new file mode 100644
index 00000000000..5c6d8470d65
--- /dev/null
+++ b/admin/report/fitandproper/qualificationadmin_filter_form.php
@@ -0,0 +1,45 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the filter form for cpd activity maintenance
+ */
+class qualificationadmin_filter_form extends moodleform {
+
+ function definition()
+ {
+
+ global $DB;
+
+ $mform = $this->_form;
+ $filteroptions = array(
+ 1=>'contains',
+ 2=>'doesn\'t contain',
+ 3=>'is equal to',
+ 4=>'starts with',
+ 5=>'ends with',
+ 6=>'is empty');
+
+ $name_elements = array();
+ $name_elements[] = $mform->createElement('select', 'qualification_name', null,$filteroptions);
+ $name_elements[] = $mform->createElement('text','qualification_name_text');
+ $mform->addGroup($name_elements, 'name_elements', get_string('qualificationadmin_filter_qualificationname', 'report_fitandproper'), array(' '), false);
+
+ $id_elements = array();
+ $id_elements[] = $mform->createElement('select', 'qualification_id', null,$filteroptions);
+ $id_elements[] = $mform->createElement('text','qualification_id_text');
+ $mform->addGroup($id_elements, 'id_elements', get_string('qualificationadmin_filter_qualificationid', 'report_fitandproper'), array(' '), false);
+
+ $mform->addElement('text','qualification_nqf_text', get_string('qualificationadmin_filter_qualificationnqf', 'report_fitandproper'));
+ $mform->addRule('qualification_nqf_text', null, 'numeric', null, 'client');
+
+ $mform->addElement('text','qualification_credits_text', get_string('qualificationadmin_filter_qualificationcredits', 'report_fitandproper'));
+ $mform->addRule('qualification_credits_text', null, 'numeric', null, 'client');
+
+ $buttonarray=array();
+ $buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('cpdactivitymaintenance_filter_submit', 'report_fitandproper'));
+ $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
+ $mform->closeHeaderBefore('buttonar');
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationadmin_report_form.php b/admin/report/fitandproper/qualificationadmin_report_form.php
new file mode 100644
index 00000000000..15833294923
--- /dev/null
+++ b/admin/report/fitandproper/qualificationadmin_report_form.php
@@ -0,0 +1,24 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the Qualification CSV file upload form
+ */
+class qualificationadmin_report_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $iid = $this->_customdata['iid'];
+ $cat_id = $this->_customdata['cat_id'];
+
+ $mform->addElement('hidden', 'iid', $iid);
+ $mform->addElement('hidden', 'cat_id', $cat_id);
+
+ $this->add_action_buttons(true,get_string('qualificationadmin_report_accept', 'report_fitandproper'));
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationadmin_upload_form.php b/admin/report/fitandproper/qualificationadmin_upload_form.php
new file mode 100644
index 00000000000..c49d2e63356
--- /dev/null
+++ b/admin/report/fitandproper/qualificationadmin_upload_form.php
@@ -0,0 +1,50 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the Qualification CSV file upload form
+ */
+class qualificationadmin_upload_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ //$op = $this->_customdata['op'];
+
+ //get list of top level categories
+ $fais_categories = $DB->get_records('fais_category',array('enabled'=>1,'deleted'=>0),'name','id,name');
+ $category_list = array(0=>get_string('qualificationadmin_formselect', 'report_fitandproper'));
+ foreach($fais_categories as $category)
+ {
+ $category_list[$category->id] = $category->name;
+ }
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('filepicker', 'csvfile', get_string('qualificationadmin_formfile', 'report_fitandproper'), null, array('maxbytes' => 8000000, 'accepted_types' => 'csv'));
+ //$mform->addElement('file', 'csvfile', get_string('qualificationadmin_formfile', 'report_fitandproper'));
+ $mform->addRule('csvfile', null, 'required');
+
+ $mform->addElement('select', 'category', get_string('qualificationadmin_formcategory', 'report_fitandproper'),$category_list);
+ $mform->addRule('category', null, 'required');
+ //$mform->addElement('hidden', 'id');
+
+ $this->add_action_buttons(true,get_string('qualificationadmin_formupload', 'report_fitandproper'));
+
+ }
+
+ function validation($data)
+ {
+ $errors = array();
+
+ if($data['category'] == 0)
+ {
+ $errors['category'] = get_string('qualificationadmin_formselect_error', 'report_fitandproper');
+ }
+
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationmaintenance.php b/admin/report/fitandproper/qualificationmaintenance.php
new file mode 100644
index 00000000000..27f12d0906f
--- /dev/null
+++ b/admin/report/fitandproper/qualificationmaintenance.php
@@ -0,0 +1,171 @@
+id === 0) {
+ $SESSION->wantsurl = $CFG->wwwroot . '/admin/report/fitandproper/qualificationmaintenance.php?'.$_SERVER['QUERY_STRING'];
+ $authplugin = get_auth_plugin('ldap');
+ if (empty($authplugin->config->ntlmsso_enabled)) {
+ redirect($CFG->wwwroot . '/login/index.php');
+ } else {
+ redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_attempt.php');
+ }
+}
+
+require_once($CFG->libdir.'/adminlib.php');
+//require_once('cpdactivityadmin_edit_form.php');
+require_once('qualificationmaintenance_filter_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewqualificationmaintenance', get_context_instance(CONTEXT_SYSTEM));
+
+$partyid = required_param('partyid',PARAM_TEXT);
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmaintenance.php";
+$url_manager = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmanager.php";
+
+// Print the header.
+admin_externalpage_setup('qualificationmaintenance');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('qualificationmaintenance_heading', 'report_fitandproper'));
+
+$display = false;
+//echo $OUTPUT->notification('test');
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+if(isset($user_details->id))
+{
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('qualificationmaintenance_usernotfound', 'report_fitandproper'));
+}
+
+if($display)
+{
+ /*
+ * Display filter
+ */
+ $filter_form = new qualificationmaintenance_filter_form(null,array('partyid'=>$partyid));
+ echo $OUTPUT->box_start('filterlist');
+ echo ' ';
+ echo ''.get_string('qualificationmaintenance_filter_head', 'report_fitandproper').' ';
+ echo '';
+ $filter_form->display();
+ echo '
';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+ /*
+ * Get list of institutions from database and apply filters if neccesary
+ */
+ if($fdata = $filter_form->get_data())
+ {
+ if(isset($fdata->enabled))
+ {
+ $where= '';
+ $params = array();
+ $where = 'completed >= ? AND completed <= ? and moodle_user_id = ?';
+ $params = array($fdata->date_from,$fdata->date_to,$user_details->id);
+ $where .= ' AND deleted = 0';
+ $qualifications = $DB->get_records_select('user_qualification',$where,$params,'completed DESC');
+ }else
+ {
+ //no filter selected so get all records
+ $qualifications = $DB->get_records('user_qualification',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+ }
+ else
+ {
+ //no filter selected so get all records
+ $qualifications = $DB->get_records('user_qualification',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+
+ /*
+ * Display user qualifications list table
+ */
+
+ echo $OUTPUT->box_start('qualificationmaintenancelist');
+ echo 'Qualifications for '.$user_details->firstname.' '.$user_details->lastname.'
';
+ echo '';
+ echo 'View user CPD ';
+ echo ' ';
+ echo 'View user Regulatory Exam Results ';
+ echo '
';
+ echo ''.get_string('qualificationmaintenance_addnew', 'report_fitandproper').'
';
+
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('qualificationmaintenance_tableheadcode', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheaddesc', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadcompleted', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadinstitution', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadnqf', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadedit', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheaddelete', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadproof', 'report_fitandproper'));
+
+ $r = array();
+
+ $context = get_system_context();
+ $fs = get_file_storage();
+
+ if(isset($qualifications) && count($qualifications) > 0)
+ {
+ foreach($qualifications as $q)
+ {
+ //get the qualification details
+ $q_details = $DB->get_record('qualification',array('id'=>$q->qualification_id),'qualification_number,title,qualification_level');
+ //get institution details
+ $i_details = $DB->get_record('institution',array('id'=>$q->institution_id),'name');
+
+ $edit = ' ';
+ $delete = ' ';
+
+ //check if file is there
+ if($q->qualification_file != null)
+ {
+ $viewproof = 'View ';
+ }else
+ {
+ $viewproof = 'None';
+ }
+
+ @$row = new html_table_row(array($q_details->qualification_number,$q_details->title,date('Y-m-d',$q->completed),$i_details->name,$q_details->qualification_level,$edit,$delete,$viewproof));
+ if($q->enabled == 0 || $q_details == false) $row->attributes = array('class'=>'faiscategorydisabled');
+ $table->data[] = $row;
+ //$table->data[] = array($i->code,$i->name,$edit,$delete);
+ }
+ }
+ else
+ {
+ $table->data[] = array(get_string('qualificationmaintenance_tablenorows', 'report_fitandproper'));
+ }
+ echo html_writer::table($table);
+
+ echo ''.get_string('qualificationmaintenance_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+// Footer.
+echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationmaintenance.php.B4_PATCH b/admin/report/fitandproper/qualificationmaintenance.php.B4_PATCH
new file mode 100644
index 00000000000..15bb53fe64d
--- /dev/null
+++ b/admin/report/fitandproper/qualificationmaintenance.php.B4_PATCH
@@ -0,0 +1,166 @@
+id === 0) {
+ $SESSION->wantsurl = $CFG->wwwroot . '/admin/report/fitandproper/qualificationmaintenance.php?'.$_SERVER['QUERY_STRING'];
+ redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_attempt.php');
+}
+
+require_once($CFG->libdir.'/adminlib.php');
+//require_once('cpdactivityadmin_edit_form.php');
+require_once('qualificationmaintenance_filter_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewqualificationmaintenance', get_context_instance(CONTEXT_SYSTEM));
+
+$partyid = required_param('partyid',PARAM_TEXT);
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmaintenance.php";
+$url_manager = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmanager.php";
+
+// Print the header.
+admin_externalpage_setup('qualificationmaintenance');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('qualificationmaintenance_heading', 'report_fitandproper'));
+
+$display = false;
+//echo $OUTPUT->notification('test');
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+if(isset($user_details->id))
+{
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('qualificationmaintenance_usernotfound', 'report_fitandproper'));
+}
+
+if($display)
+{
+ /*
+ * Display filter
+ */
+ $filter_form = new qualificationmaintenance_filter_form(null,array('partyid'=>$partyid));
+ echo $OUTPUT->box_start('filterlist');
+ echo '';
+ echo ''.get_string('qualificationmaintenance_filter_head', 'report_fitandproper').' ';
+ echo '';
+ $filter_form->display();
+ echo '
';
+ echo ' ';
+ echo $OUTPUT->box_end();
+
+ /*
+ * Get list of institutions from database and apply filters if neccesary
+ */
+ if($fdata = $filter_form->get_data())
+ {
+ if(isset($fdata->enabled))
+ {
+ $where= '';
+ $params = array();
+ $where = 'completed >= ? AND completed <= ? and moodle_user_id = ?';
+ $params = array($fdata->date_from,$fdata->date_to,$user_details->id);
+ $where .= ' AND deleted = 0';
+ $qualifications = $DB->get_records_select('user_qualification',$where,$params,'completed DESC');
+ }else
+ {
+ //no filter selected so get all records
+ $qualifications = $DB->get_records('user_qualification',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+ }
+ else
+ {
+ //no filter selected so get all records
+ $qualifications = $DB->get_records('user_qualification',array('deleted'=>0,'moodle_user_id'=>$user_details->id),'completed DESC');
+ }
+
+ /*
+ * Display user qualifications list table
+ */
+
+ echo $OUTPUT->box_start('qualificationmaintenancelist');
+ echo 'Qualifications for '.$user_details->firstname.' '.$user_details->lastname.'
';
+ echo '';
+ echo 'View user CPD ';
+ echo ' ';
+ echo 'View user Regulatory Exam Results ';
+ echo '
';
+ echo ''.get_string('qualificationmaintenance_addnew', 'report_fitandproper').'
';
+
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('qualificationmaintenance_tableheadcode', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheaddesc', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadcompleted', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadinstitution', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadnqf', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadedit', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheaddelete', 'report_fitandproper'),
+ get_string('qualificationmaintenance_tableheadproof', 'report_fitandproper'));
+
+ $r = array();
+
+ $context = get_system_context();
+ $fs = get_file_storage();
+
+ if(isset($qualifications) && count($qualifications) > 0)
+ {
+ foreach($qualifications as $q)
+ {
+ //get the qualification details
+ $q_details = $DB->get_record('qualification',array('id'=>$q->qualification_id),'qualification_number,title,qualification_level');
+ //get institution details
+ $i_details = $DB->get_record('institution',array('id'=>$q->institution_id),'name');
+
+ $edit = ' ';
+ $delete = ' ';
+
+ //check if file is there
+ if($q->qualification_file != null)
+ {
+ $viewproof = 'View ';
+ }else
+ {
+ $viewproof = 'None';
+ }
+
+ @$row = new html_table_row(array($q_details->qualification_number,$q_details->title,date('Y-m-d',$q->completed),$i_details->name,$q_details->qualification_level,$edit,$delete,$viewproof));
+ if($q->enabled == 0 || $q_details == false) $row->attributes = array('class'=>'faiscategorydisabled');
+ $table->data[] = $row;
+ //$table->data[] = array($i->code,$i->name,$edit,$delete);
+ }
+ }
+ else
+ {
+ $table->data[] = array(get_string('qualificationmaintenance_tablenorows', 'report_fitandproper'));
+ }
+ echo html_writer::table($table);
+
+ echo ''.get_string('qualificationmaintenance_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+// Footer.
+echo $OUTPUT->footer();
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationmaintenance_filter_form.php b/admin/report/fitandproper/qualificationmaintenance_filter_form.php
new file mode 100644
index 00000000000..a8d776ccfbf
--- /dev/null
+++ b/admin/report/fitandproper/qualificationmaintenance_filter_form.php
@@ -0,0 +1,27 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the filter form for qualification maintenance
+ */
+class qualificationmaintenance_filter_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+ $partyid = $this->_customdata['partyid'];
+
+ $mform->addElement('checkbox', 'enabled', get_string('qualificationmaintenance_filter_enable', 'report_fitandproper'));
+ $mform->addElement('date_selector', 'date_from', get_string('qualificationmaintenance_filter_datefrom', 'report_fitandproper'));
+ $mform->addElement('date_selector', 'date_to', get_string('qualificationmaintenance_filter_dateto', 'report_fitandproper'));
+ $mform->addElement('hidden','partyid',$partyid);
+
+ $buttonarray=array();
+ $buttonarray[] = &$mform->createElement('submit', 'submitbutton', get_string('qualificationmaintenance_filter_submit', 'report_fitandproper'));
+ $mform->addGroup($buttonarray, 'buttonar', '', array(' '), false);
+ $mform->closeHeaderBefore('buttonar');
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationmanager.php b/admin/report/fitandproper/qualificationmanager.php
new file mode 100644
index 00000000000..c9b900c4632
--- /dev/null
+++ b/admin/report/fitandproper/qualificationmanager.php
@@ -0,0 +1,241 @@
+libdir.'/adminlib.php');
+//require_once('cpdactivityadmin_edit_form.php');
+require_once('qualificationmanager_edit_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewqualificationmanager', get_context_instance(CONTEXT_SYSTEM));
+$context = get_system_context();
+
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+$partyid = required_param('partyid',PARAM_TEXT);
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmanager.php";
+$url_maintenance = "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmaintenance.php?partyid=".$partyid;
+
+// Print the header.
+admin_externalpage_setup('qualificationmanager');
+echo $OUTPUT->header();
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+
+
+$display = false;
+
+if(isset($user_details->id))
+{
+ echo $OUTPUT->heading(get_string('qualificationmanager_heading', 'report_fitandproper') . ' For ' . $user_details->firstname . ' ' . $user_details->lastname);
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('qualificationmaintenance_usernotfound', 'report_fitandproper'));
+}
+
+/*
+ * Check if user requested an add or edit institution
+ */
+if($display)
+{
+ if($op == 'add' || $op == 'edit')
+ {
+ /*
+ * get list of recognised qualifications
+ */
+ $qualifications = $DB->get_records('qualification',array('enabled'=>1,'deleted'=>0),'title','id,qualification_level');
+ $qcode = array();
+ if($qualifications)
+ {
+ foreach($qualifications as $q)
+ {
+ $qcode[$q->id] = $q->qualification_level;
+ }
+ }
+ $qcode = json_encode($qcode);
+ // Include the required JavaScript.
+ $jsmodule = array(
+ 'name' => 'report_fitandproper',
+ 'fullpath' => '/admin/report/fitandproper/module_qualificationmanager.js'); //on this line you are loading three other YUI modules
+ $PAGE->requires->js_init_call('M.report_fitandproper.init',array($qcode),false,$jsmodule);
+
+ $edit_form = new qualificationmanager_edit_form(null,array('partyid'=>$partyid,'op'=>$op,'id'=>$id));
+ $data = $edit_form->get_data();
+
+ if($edit_form->is_cancelled())
+ {
+ redirect($url_maintenance);
+ }
+ if($data)
+ {
+ /*
+ * Check if user is doing an edit
+ */
+ if($op == 'edit')
+ {
+ //edit
+ //create qualification object
+ $record = new stdClass();
+ if($data->id != null && $data->id > 0)
+ {
+ $record->id = $data->id;
+ }
+ $record->qualification_id = $data->qualification;
+ $record->institution_id = $data->institution;
+ $record->completed = $data->date_completed;
+ $record->moodle_user_id = $user_details->id;
+ //$record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->enabled = 1;
+ $record->timemodified = time();
+ $DB->update_record('user_qualification', $record, false, false);
+
+ /*
+ * Save the uploaded file
+ */
+ if($edit_form->get_file_content('proof') != false)
+ {
+ file_save_draft_area_files($data->proof, $context->id, 'report_fitandproper', 'user_qualification', $record->id);
+ $filename = $edit_form->get_new_filename('proof');
+ $DB->set_field('user_qualification', 'qualification_file', $filename, array('id'=>$record->id));
+ }else
+ {
+ //remove file if needed
+ $filename = $DB->get_field('user_qualification','qualification_file',array('id'=>$record->id));
+ if($filename)
+ {
+ $file = $fs->get_file($context->id, 'report_fitandproper', 'user_qualification', $record->id, '/', $filename);
+ if($file)
+ {
+ $file->delete();
+ }
+ $DB->set_field('user_qualification', 'qualification_file', null, array('id'=>$record->id));
+ }
+ }
+
+ // Log.
+ add_to_log(SITEID, 'User Qualifictaion', ": Edit", "report/fitandproper/qualificationmaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+ redirect($url_maintenance);
+ }
+
+ /*
+ * Add a new user qualification to the database
+ */
+ if($op == 'add')
+ {
+ //save
+ //create qualification object
+
+ $record = new stdClass();
+
+ $record->qualification_id = $data->qualification;
+ $record->institution_id = $data->institution;
+ $record->completed = $data->date_completed;
+ $record->moodle_user_id = $user_details->id;
+ $record->enabled = 1;
+ $record->qualification_file = null;
+ $record->timecreated = time();
+ $ins_id = $DB->insert_record('user_qualification', $record, true, false);
+
+ /*
+ * Save the uploaded file
+ */
+ if($edit_form->get_file_content('proof') != false)
+ {
+ file_save_draft_area_files($data->proof, $context->id, 'report_fitandproper', 'user_qualification', $ins_id);
+ $filename = $edit_form->get_new_filename('proof');
+
+ $DB->set_field('user_qualification', 'qualification_file', $filename, array('id'=>$ins_id));
+ }
+
+ // Log.
+ add_to_log(SITEID, 'User Qualifictaion', ": Add", "report/fitandproper/qualificationmaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+
+
+ redirect($url_maintenance);
+ }
+ }else
+ {
+ if($op == 'edit')
+ {
+ $draftitemid = file_get_submitted_draft_itemid('proof');
+ file_prepare_draft_area($draftitemid, $context->id, 'report_fitandproper', 'user_qualification', $id, array('subdirs' => 0, 'maxbytes' => 800000, 'maxfiles' => 1));
+ $entry->proof = $draftitemid;
+ $edit_form->set_data($entry);
+ }
+
+ $edit_form->display();
+ }
+ $display = false;
+ }
+ elseif($op == 'delete')
+ {
+ /*
+ * Handle the deletion of User Qualifications
+ */
+ if($id != null)
+ {
+ $record = new stdClass();
+ $record->id = $id;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('user_qualification', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'User Qualifictaion', ": Delete", "report/fitandproper/qualificationmaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+ }
+
+ redirect($url_maintenance);
+ }
+}
+//echo $OUTPUT->notification('test');
+
+// Footer.
+echo $OUTPUT->footer();
+
+/*
+ * Function to save the uploaded file
+ * @param $qid integer The saved user qualification id
+ * @param $file The uploaded temporary file
+ * @param $file_name The uploaded file name
+ */
+function qualificationmanager_save_proof($qid,$file,$file_name)
+{
+ global $DB,$CFG;
+
+ /*
+ * Check if directory exist
+ */
+ if(!file_exists($CFG->dataroot.'/user_qualification_proof'))
+ {
+ mkdir($CFG->dataroot.'/user_qualification_proof');
+ }
+
+ /*
+ * Move file
+ */
+ $extension = substr(strrchr($file_name,'.'),1);
+
+ if(rename($file,$CFG->dataroot.'/user_qualification_proof/'.$qid.'.'.$extension))
+ {
+ return $qid.'.'.$extension;
+ }else
+ {
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/qualificationmanager_edit_form.php b/admin/report/fitandproper/qualificationmanager_edit_form.php
new file mode 100644
index 00000000000..342aa0780aa
--- /dev/null
+++ b/admin/report/fitandproper/qualificationmanager_edit_form.php
@@ -0,0 +1,95 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the add/edit for user qualification maintenance
+ */
+class qualificationmanager_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+ $partyid = $this->_customdata['partyid'];
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+
+ /*
+ * Get all the qualifications
+ */
+ $qualifications = $DB->get_records('qualification',array('enabled'=>1,'deleted'=>0),'title','id,title,qualification_level');
+
+ $q_options = array(0=>'Select a Qualification');
+ if($qualifications)
+ {
+ foreach($qualifications as $q)
+ {
+ $q_options[$q->id] = $q->title;
+ }
+ }
+
+ /*
+ * Get all the institutions
+ */
+ $institutions = $DB->get_records('institution',array('enabled'=>1,'deleted'=>0),'name','id,name');
+ $i_options = array(0=>'Select a Institution');
+ if($institutions)
+ {
+ foreach($institutions as $i)
+ {
+ $i_options[$i->id] = $i->name;
+ }
+ }
+
+ $mform->addElement('select', 'qualification', get_string('qualificationmanager_qualification', 'report_fitandproper'), $q_options);
+ $mform->addRule('qualification', null, 'required', null, 'client');
+ $mform->addRule('qualification', 'You must select a Qualification', 'nonzero', null, 'client');
+
+ $mform->addElement('date_selector', 'date_completed', get_string('qualificationmanager_completed', 'report_fitandproper'));
+ $mform->addRule('date_completed', null, 'required', null, 'client');
+
+ $mform->addElement('select', 'institution', get_string('qualificationmanager_institution', 'report_fitandproper'), $i_options);
+ $mform->addRule('institution', null, 'required', null, 'client');
+ $mform->addRule('institution', 'You must select an Institution', 'nonzero', null, 'client');
+
+ $mform->addElement('text', 'nqf', get_string('qualificationmanager_nqf', 'report_fitandproper'),array('disabled'=>'disabled'));
+
+ $mform->addElement('filepicker', 'proof', get_string('qualificationmanager_proof', 'report_fitandproper'), null, array('maxbytes' => 8000000, 'accepted_types' => array('*.pdf','*.docx','*.doc','*.rtf','*.jpg','*.gif','*.tif','*.png')));
+ $mform->addRule('proof', null, 'required', null, 'client');
+
+ $mform->addElement('hidden','partyid',$partyid);
+ $mform->addElement('hidden','op',$op);
+ $mform->addElement('hidden','id',$id);
+
+ /*
+ * Edit form data
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $u_qualification = $DB->get_record('user_qualification',array('id'=>$id));
+
+ $mform->setDefault('qualification', $u_qualification->qualification_id);
+ $mform->setDefault('date_completed', $u_qualification->completed);
+ $mform->setDefault('institution', $u_qualification->institution_id);
+ $mform->setDefault('nqf', $qualifications[$u_qualification->qualification_id]->qualification_level);
+ }
+
+
+ $this->add_action_buttons(true,get_string('qualificationmanager_submit', 'report_fitandproper'));
+
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+ $db_file = $DB->count_records('files',array('itemid'=>$data['proof']));
+ if ($db_file == 0)
+ {
+ $errors['proof'] = get_string('required');
+ }
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamadmin.php b/admin/report/fitandproper/reexamadmin.php
new file mode 100644
index 00000000000..6c53d2c7c92
--- /dev/null
+++ b/admin/report/fitandproper/reexamadmin.php
@@ -0,0 +1,392 @@
+libdir.'/adminlib.php');
+require_once('reexamadmin_level_edit_form.php');
+require_once('reexamadmin_level_links_form.php');
+require_once('reexamadmin_exam_edit_form.php');
+require_once('reexamadmin_exam_links_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewreexams', get_context_instance(CONTEXT_SYSTEM));
+
+// Print the header.
+admin_externalpage_setup('reexamadmin');
+
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+$type = optional_param('type', null,PARAM_TEXT);
+$step = optional_param('step', null,PARAM_INTEGER);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamadmin.php";
+
+echo $OUTPUT->header();
+echo $OUTPUT->heading(get_string('reexamadmin_heading', 'report_fitandproper'));
+
+/*
+ * Check if user requested an add or edit re exam or level
+ */
+$display = true;
+if($op == 'add' || $op == 'edit' || $op == 'delete')
+{
+
+ if($type == 'top')
+ {
+ // Include the required JavaScript.
+ $jsmodule = array(
+ 'name' => 'report_fitandproper',
+ 'fullpath' => '/admin/report/fitandproper/module.js',
+ 'requires' => array("overlay", "anim", "plugin")); //on this line you are loading three other YUI modules
+ $PAGE->requires->js_init_call('M.report_fitandproper.init',null,false,$jsmodule);
+
+ $edit_form = new reexamadmin_level_edit_form(null,array('op'=>$op,'id'=>$id,'type'=>$type));
+ $data = $edit_form->get_data();
+
+ if($edit_form->is_cancelled())
+ {
+ redirect($url);
+ }elseif($data || $step == 2 || $op == 'delete')
+ {
+ if($op == 'add')
+ {
+ $record = new stdClass();
+ $record->name = $data->name;
+ $record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->timemodified = time();
+ $record->timecreated = time();
+ $ins_id = $DB->insert_record('re_level', $record, true, false);
+
+ if(isset($_POST['subcategory']))
+ {
+ foreach($_POST['subcategory'] as $catid)
+ {
+ $cat_record = new stdClass();
+ $cat_record->re_level_id = $ins_id;
+ $cat_record->fais_sub_category_id = $catid;
+ $DB->insert_record('re_level_fais_sub_cat', $cat_record, false, false);
+ }
+ }
+
+ // Log.
+ add_to_log(SITEID, 'RE Level', ": Add", "report/fitandproper/releveladmin.php",$record->name);
+ redirect($url);
+ }
+ if($op == 'edit' || $op == 'delete')
+ {
+ $links_form = new reexamadmin_level_links_form(null,array('edit_form'=>$data,'id'=>$id,'op'=>$op,'type'=>$type));
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($ldata = $links_form->get_data())
+ {
+ if($op == 'edit')
+ {
+ $record = new stdClass();
+ $record->id = $id;
+ $record->name = $ldata->name;
+ $record->enabled = (isset($ldata->enabled)) ? (int)$ldata->enabled : 0;
+ $record->timemodified = time();
+ $DB->update_record('re_level', $record, false);
+
+ $DB->delete_records('re_level_fais_sub_cat',array('re_level_id'=>$record->id));
+ if(isset($_POST['subcategory']))
+ {
+ foreach($_POST['subcategory'] as $catid)
+ {
+ $cat_record = new stdClass();
+ $cat_record->re_level_id = $id;
+ $cat_record->fais_sub_category_id = $catid;
+ $DB->insert_record('re_level_fais_sub_cat', $cat_record, false, false);
+ }
+ }
+
+ // Log.
+ add_to_log(SITEID, 'RE Level', ": Edit", "report/fitandproper/releveladmin.php",$record->name);
+ redirect($url);
+ }elseif($op == 'delete')
+ {
+ require_capability('report/fitandproper:deletereexams', get_context_instance(CONTEXT_SYSTEM));
+ $record = new stdClass();
+ $record->id = $id;
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('re_level', $record, false);
+
+ if($ldata->replace_level == '0')
+ {
+ $DB->set_field('re_exam', 'deleted', 1, array('re_level_id'=>$ldata->id));
+ $DB->set_field('re_exam_result', 'deleted', 1, array('re_level_id'=>$ldata->id));
+ }else
+ {
+ $DB->set_field('re_exam', 're_level_id', $ldata->replace_level, array('re_level_id'=>$ldata->id));
+ $DB->set_field('re_exam_result', 're_level_id', $ldata->replace_level, array('re_level_id'=>$ldata->id));
+ }
+
+ // Log.
+ $re_name = $DB->get_record('re_level',array('id'=>$id));
+ add_to_log(SITEID, 'RE Level', ": Delete", "report/fitandproper/releveladmin.php",$re_name->name);
+ redirect($url);
+ }
+ }else
+ {
+ display_relevel_links($id);
+
+ $links_form->display();
+ }
+ }
+ }else
+ {
+ $edit_form->display();
+ }
+ $display = false;
+ }else
+ {
+ $edit_form = new reexamadmin_exam_edit_form(null,array('op'=>$op,'id'=>$id,'type'=>$type));
+ $data = $edit_form->get_data();
+
+ if($edit_form->is_cancelled())
+ {
+ redirect($url);
+ }elseif($data || $step == 2 || $op == 'delete')
+ {
+ if($op == 'add')
+ {
+ $record = new stdClass();
+ $record->re_level_id = $data->level;
+ $record->name = $data->name;
+ $record->exam_number = $data->number;
+ $record->pass_mark = $data->pass;
+ $record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->timemodified = time();
+ $record->timecreated = time();
+ $ins_id = $DB->insert_record('re_exam', $record, true, false);
+
+ // Log.
+ add_to_log(SITEID, 'RE Exam', ": Add", "report/fitandproper/releveladmin.php",$record->name);
+ redirect($url);
+ }
+ if($op == 'edit' || $op == 'delete')
+ {
+ $links_form = new reexamadmin_exam_links_form(null,array('edit_form'=>$data,'id'=>$id,'op'=>$op,'type'=>$type));
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }
+ if($ldata = $links_form->get_data())
+ {
+ if($op == 'edit')
+ {
+ $record = new stdClass();
+ $record->id = $id;
+ $record->re_level_id = $ldata->level;
+ $record->name = $ldata->name;
+ $record->exam_number = $ldata->number;
+ $record->pass_mark = $ldata->pass;
+ $record->enabled = (isset($ldata->enabled)) ? (int)$ldata->enabled : 0;
+ $record->timemodified = time();
+ $DB->update_record('re_exam', $record);
+
+ // Log.
+ add_to_log(SITEID, 'RE Exam', ": Edit", "report/fitandproper/releveladmin.php",$record->name);
+ redirect($url);
+ }elseif($op == 'delete')
+ {
+ require_capability('report/fitandproper:deletereexams', get_context_instance(CONTEXT_SYSTEM));
+ $record = new stdClass();
+ $record->id = $ldata->id;
+ $record->enabled = 0;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('re_exam', $record);
+
+ // Log.
+ $re_name = $DB->get_record('re_exam',array('id'=>$ldata->id));
+ add_to_log(SITEID, 'RE Exam', ": Delete", "report/fitandproper/releveladmin.php",$re_name->name);
+ redirect($url);
+ }
+ }else
+ {
+ display_reexam_links($id);
+
+ $links_form->display();
+ }
+ }
+ }else
+ {
+ $edit_form->display();
+ }
+ $display = false;
+ }
+}
+
+if($display)
+{
+
+ //add new exam button
+ echo '';
+ echo '
';
+ echo '';
+ echo '
';
+ echo '
';
+ echo '';
+ echo '
';
+ echo '
';
+ echo '
';
+
+
+ //get all enabled RE Exam levels
+ $re_exam_levels = $DB->get_records('re_level',array('deleted'=>0),'name');
+
+ //display table with exams
+ echo '';
+
+ //add new exam button
+ echo '';
+ echo '
';
+ echo '';
+ echo '
';
+ echo '
';
+ echo '';
+ echo '
';
+ echo '
';
+ echo '
';
+
+}
+// Footer.
+echo $OUTPUT->footer();
+
+/**
+ * Function to display a report of all the RE Exams linked to a RE Level
+ * @param $re_level integer ID of the RE Level being edited or deleted
+ */
+function display_relevel_links($re_level)
+{
+ global $DB;
+
+ $re_level_details = $DB->get_record('re_level',array('id'=>$re_level));
+
+ $re_exams = $DB->get_records('re_exam',array('re_level_id'=>$re_level,'deleted'=>0));
+
+ /*
+ * Display the table
+ */
+ echo ''.get_string('reexamadmin_report_heading', 'report_fitandproper').' '.$re_level_details->name.' ';
+ $table = new html_table();
+ //$table->attributes = array('class'=>'center');
+ $table->head = array(get_string('reexamadmin_report_exam_name', 'report_fitandproper'),get_string('reexamadmin_report_exam_code', 'report_fitandproper'),get_string('reexamadmin_report_grades_uploaded', 'report_fitandproper'));
+
+ if($re_exams)
+ {
+ foreach($re_exams as $exam)
+ {
+ /*
+ * Get exam results for exam
+ */
+ $r_count = $DB->count_records('re_exam_result',array('re_exam_id'=>$exam->id,'deleted'=>0));
+
+ $row = array($exam->name,$exam->exam_number,$r_count);
+ $table->data[] = $row;
+ }
+ }else
+ {
+ $row = array(get_string('reexamadmin_report_no_exams', 'report_fitandproper'));
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+}
+
+/**
+ * Function to display a report of all the Users linked to a RE Exam
+ * @param $re_exam integer ID of the RE Exam being edited or deleted
+ */
+function display_reexam_links($re_exam)
+{
+ global $DB;
+
+ $re_exam_details = $DB->get_record('re_exam',array('id'=>$re_exam));
+
+ $re_exam_users = $DB->get_records('re_exam_result',array('re_exam_id'=>$re_exam,'deleted'=>0));
+
+ /*
+ * Display the table
+ */
+ echo ''.get_string('reexamadmin_report_exam_heading', 'report_fitandproper').' '.$re_exam_details->name.' ';
+ $table = new html_table();
+ //$table->attributes = array('class'=>'center');
+ $table->head = array(get_string('reexamadmin_report_exam_user', 'report_fitandproper'),get_string('reexamadmin_report_exam_grade', 'report_fitandproper'));
+
+ if($re_exam_users)
+ {
+ foreach($re_exam_users as $exam)
+ {
+
+ $row = array($exam->title.' '.$exam->initials.' '.$exam->surname,$exam->result);
+ $table->data[] = $row;
+ }
+ }else
+ {
+ $row = array(get_string('reexamadmin_report_no_exam_user', 'report_fitandproper'));
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamadmin_exam_edit_form.php b/admin/report/fitandproper/reexamadmin_exam_edit_form.php
new file mode 100644
index 00000000000..1fabea5c9a5
--- /dev/null
+++ b/admin/report/fitandproper/reexamadmin_exam_edit_form.php
@@ -0,0 +1,114 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the RE Exams exam add/edit form
+ */
+class reexamadmin_exam_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+ $type = $this->_customdata['type'];
+
+ /*
+ * if this is a edit form get the data for edit
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $data = $DB->get_record('re_exam',array('id'=>$id,'deleted'=>0));
+ }
+
+ /*
+ * get list of re levels
+ */
+ $re_levels = $DB->get_records('re_level',array('deleted'=>0,'enabled'=>1),'name','id,name');
+ $level_list = array('0'=>'Please select ...');
+ foreach($re_levels as $l)
+ {
+ $level_list[$l->id] = $l->name;
+ }
+
+ if($op == 'edit')
+ {
+ $mform->setDefault('id', $id);
+ $mform->setDefault('level', $data->re_level_id);
+ $mform->setDefault('name', $data->name);
+ $mform->setDefault('number', $data->exam_number);
+ $mform->setDefault('pass', $data->pass_mark);
+ $mform->setDefault('enabled', $data->enabled);
+
+ }else
+ {
+ $mform->setDefault('enabled', 1);
+ }
+
+ $header = ($op == 'edit') ? 'Edit' : 'Add new';
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('select', 'level', get_string('reexamadmin_examlevel', 'report_fitandproper'), $level_list);
+ $mform->addRule('level', null, 'required', null, 'client');
+
+ $mform->addElement('text', 'number', get_string('reexamadmin_examnumber', 'report_fitandproper'));
+ $mform->addRule('number', null, 'required', null, 'client');
+ $mform->addRule('number', null, 'maxlength', 255, 'client');
+ $mform->addRule('number', null, 'alphanumeric', null, 'client');
+
+ $mform->addElement('text', 'name', get_string('reexamadmin_examname', 'report_fitandproper'));
+ $mform->addRule('name', null, 'required', null, 'client');
+ $mform->addRule('name', null, 'maxlength', 255, 'client');
+ $mform->addRule('name', get_string('reexamadmin_nameformat', 'report_fitandproper'), 'regex', "/^[a-zA-Z0-9\s]+$/", 'client');
+
+ $mform->addElement('text', 'pass', get_string('reexamadmin_exampass', 'report_fitandproper'));
+ $mform->addRule('pass', null, 'required', null, 'client');
+ $mform->addRule('pass', null, 'maxlength', 5, 'client');
+ $mform->addRule('pass', null, 'numeric', null, 'client');
+ $mform->addRule('pass', null, 'nopunctuation', null, 'client');
+
+ $mform->addElement('checkbox', 'enabled', get_string('enabled', 'report_fitandproper'));
+
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'type', $type);
+ $mform->addElement('hidden', 'id');
+
+ $this->add_action_buttons(true,get_string('reexamadmin_submit', 'report_fitandproper'));
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+
+ //check for duplicate name
+ $check = $DB->count_records_select('re_exam','deleted = 0 and name = ? and id != ?',array($data['name'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['name'] = get_string('reexamadmin_submit_duplicate_name', 'report_fitandproper');
+ }
+
+ //check for duplicate number
+ $check = $DB->count_records_select('re_exam','deleted = 0 and exam_number = ? and id != ?',array($data['number'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['number'] = get_string('reexamadmin_submit_duplicate_number', 'report_fitandproper');
+ }
+
+ //check that a level is selected
+ if($data['level'] == 0)
+ {
+ $errors['level'] = get_string('reexamadmin_submit_nolevel', 'report_fitandproper');
+ }
+
+ return $errors;
+ }
+}
+?>
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamadmin_exam_links_form.php b/admin/report/fitandproper/reexamadmin_exam_links_form.php
new file mode 100644
index 00000000000..9eea4089885
--- /dev/null
+++ b/admin/report/fitandproper/reexamadmin_exam_links_form.php
@@ -0,0 +1,50 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the RE Levels edit links report form
+ */
+class reexamadmin_exam_links_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $edit_form = $this->_customdata['edit_form'];
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+ $type = $this->_customdata['type'];
+ //$can_save = $this->_customdata['can_save'];
+
+ if($op == 'edit')
+ {
+ $mform->addElement('hidden', 'id', $edit_form->id);
+ $mform->addElement('hidden', 'name', $edit_form->name);
+ $mform->addElement('hidden', 'level', $edit_form->level);
+ $mform->addElement('hidden', 'number', $edit_form->number);
+ $mform->addElement('hidden', 'pass', $edit_form->pass);
+ $mform->addElement('hidden', 'type', $edit_form->type);
+ $mform->addElement('hidden', 'enabled', $edit_form->enabled);
+ $mform->addElement('hidden', 'op', $edit_form->op);
+ $mform->addElement('hidden', 'step', 2);
+ }elseif($op == 'delete')
+ {
+ $mform->addElement('hidden', 'id', $id);
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'step', 2);
+ $mform->addElement('hidden', 'type', $type);
+ }
+
+ if($op == 'edit')
+ {
+ $this->add_action_buttons(true,get_string('reexamadmin_report_submit', 'report_fitandproper'));
+ }else
+ {
+ $this->add_action_buttons(true,get_string('reexamadmin_report_submit_delete_exam', 'report_fitandproper'));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamadmin_level_edit_form.php b/admin/report/fitandproper/reexamadmin_level_edit_form.php
new file mode 100644
index 00000000000..6d2e6979340
--- /dev/null
+++ b/admin/report/fitandproper/reexamadmin_level_edit_form.php
@@ -0,0 +1,120 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the RE Exams level add/edit form
+ */
+class reexamadmin_level_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+ $type = $this->_customdata['type'];
+
+ /*
+ * if this is a edit form get the activity data for edit
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $data = $DB->get_record('re_level',array('id'=>$id,'deleted'=>0));
+ }
+
+ /*
+ * get list of top level categories
+ */
+ $fais_categories = $DB->get_records('fais_category',array('deleted'=>0,'enabled'=>1),'name','id,name');
+ $category_list = array('0'=>'Please select ...');
+ foreach($fais_categories as $category)
+ {
+ $category_list[$category->id] = $category->name;
+ }
+
+ $fais_sub_categories = array(0=>'Please select a category');
+ if($op == 'edit')
+ {
+ $mform->setDefault('id', $id);
+ $mform->setDefault('name', $data->name);
+ $mform->setDefault('enabled', $data->enabled);
+
+ //get and set categories
+ $sub_categories = $DB->get_records_sql('SELECT * FROM {re_level_fais_sub_cat} scl INNER JOIN {fais_sub_category} sc ON (scl.fais_sub_category_id = sc.id) WHERE scl.re_level_id = ? ORDER BY sc.name',array($id));
+
+ $top = 0;
+ $fais_sub_categories = array();
+ $sub_categories_defaults = array();
+ foreach($sub_categories as $sc)
+ {
+ $top = $sc->fais_category_id;
+ $sub_categories_defaults[] = $sc->fais_sub_category_id;
+ }
+
+ //get all sub categories
+ $sub_categories = $DB->get_records('fais_sub_category',array('fais_category_id'=>$top,'enabled'=>1,'deleted'=>0),'name','id,name');
+ foreach($sub_categories as $sc)
+ {
+ $fais_sub_categories[$sc->id] = $sc->name;
+ }
+
+ $mform->setDefault('subcategory', $sub_categories_defaults);
+ $mform->setDefault('category', $top);
+
+ }else
+ {
+ $mform->setDefault('enabled', 1);
+ }
+
+ $header = ($op == 'edit') ? 'Edit' : 'Add a new';
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('text', 'name', get_string('reexamadmin_levelname', 'report_fitandproper'));
+ $mform->addRule('name', null, 'required', null, 'client');
+ $mform->addRule('name', null, 'maxlength', 255, 'client');
+ $mform->addRule('name', null, 'alphanumeric', null, 'client');
+ $mform->addElement('select', 'category', get_string('cpdactivity_category', 'report_fitandproper'), $category_list);
+
+ $subselect = $mform->addElement('select', 'subcategory', get_string('cpdactivity_subcategory', 'report_fitandproper'), $fais_sub_categories);
+ $subselect->setMultiple(true);
+ $mform->disabledIf('subcategory', 'category', 'eq', 0);
+
+ $mform->addElement('checkbox', 'enabled', get_string('enabled', 'report_fitandproper'));
+
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'type', $type);
+ $mform->addElement('hidden', 'id');
+
+ $this->add_action_buttons(true,get_string('reexamadmin_submit', 'report_fitandproper'));
+ }
+
+ function validation($data)
+ {
+ global $DB;
+
+ $errors = array();
+
+ //check for duplicate name
+ $check = $DB->count_records_select('re_level','deleted = 0 and name = ? and id != ?',array($data['name'],$data['id']));
+
+ if($check > 0)
+ {
+ $errors['name'] = get_string('reexamadmin_submit_duplicate_name', 'report_fitandproper');
+ }
+
+ //check that a sub category is selected when top category is selected
+ if($data['category'] > 0)
+ {
+ if(!isset($_POST['subcategory']) || $_POST['subcategory'][0] == '0')
+ {
+ $errors['subcategory'] = get_string('reexamadmin_submit_nosub', 'report_fitandproper');
+ }
+ }
+
+ return $errors;
+ }
+}
+?>
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamadmin_level_links_form.php b/admin/report/fitandproper/reexamadmin_level_links_form.php
new file mode 100644
index 00000000000..fa658ac2f6a
--- /dev/null
+++ b/admin/report/fitandproper/reexamadmin_level_links_form.php
@@ -0,0 +1,70 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the RE Levels edit links report form
+ */
+class reexamadmin_level_links_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $edit_form = $this->_customdata['edit_form'];
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+ $type = $this->_customdata['type'];
+ //$can_save = $this->_customdata['can_save'];
+
+ if($op == 'edit')
+ {
+ $mform->addElement('hidden', 'id', $edit_form->id);
+ $mform->addElement('hidden', 'name', $edit_form->name);
+ $mform->addElement('hidden', 'type', $edit_form->type);
+ @$mform->addElement('hidden', 'enabled', $edit_form->enabled);
+ $mform->addElement('hidden', 'op', $edit_form->op);
+ $mform->addElement('hidden', 'step', 2);
+
+ //use POST because Moodle does not like a selectbox that was filled by ajax
+ if(isset($_POST['subcategory']))
+ {
+ foreach($_POST['subcategory'] as $sc)
+ {
+ $mform->addElement('hidden', 'subcategory[]', $sc);
+ }
+ }
+ }elseif($op == 'delete')
+ {
+ $mform->addElement('hidden', 'id', $id);
+ $mform->addElement('hidden', 'op', $op);
+ $mform->addElement('hidden', 'step', 2);
+ $mform->addElement('hidden', 'type', $type);
+ }
+
+ if($op == 'edit')
+ {
+ $this->add_action_buttons(true,get_string('reexamadmin_report_submit', 'report_fitandproper'));
+ }else
+ {
+ $mform->addElement('html', ''.get_string('reexamadmin_report_deleteinfo', 'report_fitandproper').'
');
+
+ /*
+ * Display select box for what to do with linked exams
+ */
+ $levels = $DB->get_records('re_level',array('deleted'=>0,'enabled'=>1),'name');
+ $level_list = array('0'=>'None, all linked RE Exams and associated RE Exam Grades should be deleted.');
+ foreach($levels as $l)
+ {
+ $level_list[$l->id] = $l->name;
+ }
+ unset($level_list[$id]);
+ $mform->addElement('select','replace_level','',$level_list);
+
+ $this->add_action_buttons(true,get_string('reexamadmin_report_submit_delete', 'report_fitandproper'));
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamresultsmaintenance.php b/admin/report/fitandproper/reexamresultsmaintenance.php
new file mode 100644
index 00000000000..b28cdd7c6a3
--- /dev/null
+++ b/admin/report/fitandproper/reexamresultsmaintenance.php
@@ -0,0 +1,114 @@
+id === 0) {
+ $SESSION->wantsurl = $CFG->wwwroot . '/admin/report/fitandproper/reexamresultsmaintenance.php?'.$_SERVER['QUERY_STRING'];
+ $authplugin = get_auth_plugin('ldap');
+ if (empty($authplugin->config->ntlmsso_enabled)) {
+ redirect($CFG->wwwroot . '/login/index.php');
+ } else {
+ redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_attempt.php');
+ }
+}
+
+require_once($CFG->libdir.'/adminlib.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_capability('report/fitandproper:viewreexamresultsmaintenance', get_context_instance(CONTEXT_SYSTEM));
+
+$partyid = required_param('partyid',PARAM_TEXT);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmaintenance.php";
+$url_manager = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmanager.php";
+
+
+admin_externalpage_setup('reexamresultsmaintenance');
+
+// Print the header.
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('reexamresultsmaintenance_heading', 'report_fitandproper'));
+
+require_login();
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+$display = false;
+
+if(isset($user_details->id)) {
+ $display = true;
+}else{
+ echo $OUTPUT->notification(get_string('reexamresultsmaintenance_usernotfound', 'report_fitandproper'));
+}
+
+
+if($display) {
+
+ /*
+ * Display list of reexam results
+ */
+ $reexamresults = $DB->get_records_sql("SELECT r.id,r.re_level_id,l.name as level_name,e.exam_number,r.result,e.name as exam_name
+ FROM {re_exam_result} r
+ INNER JOIN {re_level} l ON (r.re_level_id = l.id)
+ INNER JOIN {re_exam} e ON (r.re_exam_id = e.id)
+ WHERE r.deleted = 0 AND r.moodle_user_id = ?
+ ORDER BY l.name,e.exam_number",array($user_details->id));
+ echo $OUTPUT->box_start('reexamresultsmaintenancelist');
+ echo 'Re Exam Results for '.$user_details->firstname.' '.$user_details->lastname.'
';
+ echo '';
+ echo 'View user CPD ';
+ echo ' ';
+ echo 'View user Qualification ';
+ echo '
';
+ echo ''.get_string('reexamresultsmaintenance_addnew', 'report_fitandproper').'
';
+
+ //Display reexam results in table
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('reexamresultsmaintenance_tableheadreexamnumber', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadreexamlevel', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadreexamname', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadresult', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadedit', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheaddelete', 'report_fitandproper'));
+
+ if(count($reexamresults) > 0) {
+ foreach($reexamresults as $r) {
+ $edit = ' ';
+ $delete = ' ';
+
+ $row = new html_table_row(array($r->exam_number,$r->level_name,$r->exam_name,$r->result,$edit,$delete));
+ $table->data[] = $row;
+
+ }
+
+ }
+ else {
+ $table->data[] = array(get_string('reexamresultsmaintenance_tablenorows', 'report_fitandproper'));
+ }
+
+ echo html_writer::table($table);
+
+ echo ''.get_string('reexamresultsmaintenance_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+
+// Footer.
+echo $OUTPUT->footer();
+
+?>
diff --git a/admin/report/fitandproper/reexamresultsmaintenance.php.B4_PATCH b/admin/report/fitandproper/reexamresultsmaintenance.php.B4_PATCH
new file mode 100644
index 00000000000..89d991e4b4d
--- /dev/null
+++ b/admin/report/fitandproper/reexamresultsmaintenance.php.B4_PATCH
@@ -0,0 +1,109 @@
+id === 0) {
+ $SESSION->wantsurl = $CFG->wwwroot . '/admin/report/fitandproper/reexamresultsmaintenance.php?'.$_SERVER['QUERY_STRING'];
+ redirect($CFG->wwwroot . '/auth/ldap/ntlmsso_attempt.php');
+}
+
+require_once($CFG->libdir.'/adminlib.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_capability('report/fitandproper:viewreexamresultsmaintenance', get_context_instance(CONTEXT_SYSTEM));
+
+$partyid = required_param('partyid',PARAM_TEXT);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmaintenance.php";
+$url_manager = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmanager.php";
+
+
+admin_externalpage_setup('reexamresultsmaintenance');
+
+// Print the header.
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('reexamresultsmaintenance_heading', 'report_fitandproper'));
+
+require_login();
+
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+$display = false;
+
+if(isset($user_details->id)) {
+ $display = true;
+}else{
+ echo $OUTPUT->notification(get_string('reexamresultsmaintenance_usernotfound', 'report_fitandproper'));
+}
+
+
+if($display) {
+
+ /*
+ * Display list of reexam results
+ */
+ $reexamresults = $DB->get_records_sql("SELECT r.id,r.re_level_id,l.name as level_name,e.exam_number,r.result,e.name as exam_name
+ FROM {re_exam_result} r
+ INNER JOIN {re_level} l ON (r.re_level_id = l.id)
+ INNER JOIN {re_exam} e ON (r.re_exam_id = e.id)
+ WHERE r.deleted = 0 AND r.moodle_user_id = ?
+ ORDER BY l.name,e.exam_number",array($user_details->id));
+ echo $OUTPUT->box_start('reexamresultsmaintenancelist');
+ echo 'Re Exam Results for '.$user_details->firstname.' '.$user_details->lastname.'
';
+ echo '';
+ echo 'View user CPD ';
+ echo ' ';
+ echo 'View user Qualification ';
+ echo '
';
+ echo ''.get_string('reexamresultsmaintenance_addnew', 'report_fitandproper').'
';
+
+ //Display reexam results in table
+ $table = new html_table();
+ $table->attributes = array('align'=>'center');
+ $table->head = array(get_string('reexamresultsmaintenance_tableheadreexamnumber', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadreexamlevel', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadreexamname', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadresult', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheadedit', 'report_fitandproper'),
+ get_string('reexamresultsmaintenance_tableheaddelete', 'report_fitandproper'));
+
+ if(count($reexamresults) > 0) {
+ foreach($reexamresults as $r) {
+ $edit = ' ';
+ $delete = ' ';
+
+ $row = new html_table_row(array($r->exam_number,$r->level_name,$r->exam_name,$r->result,$edit,$delete));
+ $table->data[] = $row;
+
+ }
+
+ }
+ else {
+ $table->data[] = array(get_string('reexamresultsmaintenance_tablenorows', 'report_fitandproper'));
+ }
+
+ echo html_writer::table($table);
+
+ echo ''.get_string('reexamresultsmaintenance_addnew', 'report_fitandproper').'
';
+ echo $OUTPUT->box_end();
+}
+
+
+// Footer.
+echo $OUTPUT->footer();
+
+?>
diff --git a/admin/report/fitandproper/reexamresultsmanager.php b/admin/report/fitandproper/reexamresultsmanager.php
new file mode 100644
index 00000000000..3a324207088
--- /dev/null
+++ b/admin/report/fitandproper/reexamresultsmanager.php
@@ -0,0 +1,164 @@
+libdir.'/adminlib.php');
+
+require_once('reexamresultsmanager_edit_form.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+require_capability('report/fitandproper:viewreexamresultsmanager', get_context_instance(CONTEXT_SYSTEM));
+
+$op = optional_param('op', null,PARAM_TEXT);
+$id = optional_param('id', null,PARAM_INTEGER);
+
+$partyid = required_param('partyid',PARAM_TEXT);
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmanager.php";
+$url_maintenance = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmaintenance.php?partyid=".$partyid;
+$context = get_system_context();
+
+// Print the header.
+admin_externalpage_setup('reexamresultsmanager');
+echo $OUTPUT->header();
+
+
+$display = false;
+/*
+ * Check if the user exist in Moodle and get user details
+ */
+$user_details = $DB->get_record_sql("
+ SELECT * FROM mdl_user WHERE id = (SELECT TOP 1 userid FROM mdl_user_info_data
+ JOIN mdl_user_info_field ON mdl_user_info_field.id=mdl_user_info_data.fieldid
+ WHERE SUBSTRING(master.dbo.fn_varbintohexstr(HashBytes('MD5',CONVERT(varchar,data))), 3, 32) = '$partyid' AND shortname = 'partyid')
+ ");
+
+
+if(isset($user_details->id))
+{
+ echo $OUTPUT->heading(get_string('reexamresultsmanager_heading', 'report_fitandproper') . ' For ' . $user_details->firstname . ' ' . $user_details->lastname);
+ $display = true;
+}else
+{
+ echo $OUTPUT->notification(get_string('reexamresultsmaintenance_usernotfound', 'report_fitandproper'));
+}
+
+/*
+ * Check if user requested an add or edit reexam result
+ */
+if($display)
+{
+ if($op == 'add' || $op == 'edit')
+ {
+
+ // Include the required JavaScript.
+ $jsmodule = array(
+ 'name' => 'report_fitandproper',
+ 'fullpath' => '/admin/report/fitandproper/module_reexamresultsmanager.js');
+ $PAGE->requires->js_init_call('M.report_fitandproper.init',null,false,$jsmodule);
+
+ $edit_form = new reexamresultsmanager_edit_form(null,array('partyid'=>$partyid,'op'=>$op,'id'=>$id));
+ $data = $edit_form->get_data();
+ if($edit_form->is_cancelled())
+ {
+ redirect($url_maintenance);
+ }
+ if($data)
+ {
+ /*
+ * Check if user is doing an edit
+ */
+ if($op == 'edit')
+ {
+ //edit
+ //create reexam result object
+ $record = new stdClass();
+ if($data->id != null && $data->id > 0)
+ {
+ $record->id = $data->id;
+ }
+ $record->re_level_id = $data->level;
+ $record->re_exam_id = $_POST['re_exam'];
+ $record->result = $data->result;
+ $record->moodle_user_id = $user_details->id;
+ //$record->enabled = (isset($data->enabled)) ? (int)$data->enabled : 0;
+ $record->enabled = 1;
+ $record->timemodified = time();
+ $DB->update_record('re_exam_result', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'Re Exam Results', ": Edit", "report/fitandproper/reexamresultsmaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+ redirect($url_maintenance);
+ }
+
+ /*
+ * Add a new reexam result to the database
+ */
+ if($op == 'add')
+ {
+ //save
+ //create reexam result object
+
+ $record = new stdClass();
+ $re_exam_id = $_POST['re_exam'];
+ $exam = $DB->get_record('re_exam',array('id'=>$re_exam_id));
+ $record->re_level_id = $data->level;
+ $record->re_exam_id = $re_exam_id;
+ $record->result = $data->result;
+ $record->moodle_user_id = $user_details->id;
+
+ $record->surname = $user_details->lastname;
+ $record->initials = $user_details->firstname;
+ $record->email = $user_details->email;
+ $record->mobile = $user_details->phone1;
+ $record->id_number = $user_details->idnumber;
+ $record->exam = $exam->name;
+
+ $record->enabled = 1;
+ $record->timecreated = time();
+
+
+ $ins_id = $DB->insert_record('re_exam_result', $record, true, false);
+
+ // Log.
+ add_to_log(SITEID, 'Re Exam Results', ": Add", "report/fitandproper/reexamresultsmaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+
+ redirect($url_maintenance);
+ }
+ }else
+ {
+ $edit_form->display();
+ }
+ $display = false;
+ }
+ elseif($op == 'delete')
+ {
+ /*
+ * Handle the deletion of Reexam result
+ */
+ if($id != null)
+ {
+ $record = new stdClass();
+ $record->id = $id;
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('re_exam_result', $record, false, false);
+
+ // Log.
+ add_to_log(SITEID, 'Re Exam Results', ": Delete", "report/fitandproper/reexamresultsmaintenance.php",$user_details->firstname.' '.$user_details->lastname);
+ }
+
+ redirect($url_maintenance);
+ }
+}
+
+
+// Footer.
+echo $OUTPUT->footer();
diff --git a/admin/report/fitandproper/reexamresultsmanager_ajax.php b/admin/report/fitandproper/reexamresultsmanager_ajax.php
new file mode 100644
index 00000000000..6df73e5cb59
--- /dev/null
+++ b/admin/report/fitandproper/reexamresultsmanager_ajax.php
@@ -0,0 +1,35 @@
+libdir.'/adminlib.php');
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+require_login();
+
+require_capability('report/fitandproper:viewreexamresultsmanager', get_context_instance(CONTEXT_SYSTEM));
+
+$lid = (int)$_GET['lid'];
+if($lid > 0) {
+
+ $exams = $DB->get_records('re_exam',array('enabled'=>1,'deleted'=>0,'re_level_id'=>$lid),'name','id,name');
+ $count = count($exams);
+
+ $return = array();
+ if($count > 0) {
+ $return['count'] = $count;
+ foreach($exams as $e) {
+ $return['exams'][$e->id] = $e->name;
+ }
+ print json_encode($return);
+ } else {
+ print json_encode(array('count'=>0));
+ }
+
+}
+?>
\ No newline at end of file
diff --git a/admin/report/fitandproper/reexamresultsmanager_edit_form.php b/admin/report/fitandproper/reexamresultsmanager_edit_form.php
new file mode 100644
index 00000000000..50451d317fb
--- /dev/null
+++ b/admin/report/fitandproper/reexamresultsmanager_edit_form.php
@@ -0,0 +1,78 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the add/edit for user reexam result
+ */
+class reexamresultsmanager_edit_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+ $partyid = $this->_customdata['partyid'];
+ $op = $this->_customdata['op'];
+ $id = $this->_customdata['id'];
+
+ /*
+ * Get all the results
+ */
+ $levels = $DB->get_records('re_level',array('enabled'=>1,'deleted'=>0),'name','id,name');
+ $l_options = array(0=>'Select a Re Level');
+ if($levels)
+ {
+ foreach($levels as $l)
+ {
+ $l_options[$l->id] = $l->name;
+ }
+ }
+
+ $e_options = array(0=>"Select Re Level first");
+ /*
+ * Edit form data
+ */
+ if($op == 'edit' && $id != null)
+ {
+ $reexam_result = $DB->get_record('re_exam_result',array('id'=>$id));
+
+ $mform->setDefault('level', $reexam_result->re_level_id);
+
+ $exams = $DB->get_records('re_exam',array('enabled'=>1,'deleted'=>0,'re_level_id'=>$reexam_result->re_level_id),'name','id,name');
+ $count = count($exams);
+
+ if($count > 0)
+ {
+ foreach($exams as $e)
+ {
+ $e_options[$e->id] = $e->name;
+ }
+ }
+ $mform->setDefault('re_exam', $reexam_result->re_exam_id);
+ $mform->setDefault('result', $reexam_result->result);
+
+ }
+
+ $mform->addElement('select', 'level', get_string('reexamresultsmanager_level', 'report_fitandproper'), $l_options);
+ $mform->addRule('level', null, 'required', null, 'client');
+ $mform->addRule('level', 'You must select a Re Exam Level', 'nonzero', null, 'client');
+
+ $mform->addElement('select', 're_exam', get_string('reexamresultsmanager_exam', 'report_fitandproper'), $e_options);
+ $mform->addRule('re_exam', null, 'required', null, 'client');
+ $mform->addRule('re_exam', 'You must select an Exam', 'nonzero', null, 'client');
+
+ $mform->addElement('text', 'result', get_string('reexamresultsmanager_result', 'report_fitandproper'));
+ $mform->addRule('result', null, 'required', null, 'client');
+ $mform->addRule('result', null, 'numeric', null, 'client');
+ $mform->addRule('result', null, 'nopunctuation', null, 'client');
+
+ $mform->addElement('hidden','partyid',$partyid);
+ $mform->addElement('hidden','op',$op);
+ $mform->addElement('hidden','id',$id);
+
+
+ $this->add_action_buttons(true,get_string('qualificationmanager_submit', 'report_fitandproper'));
+
+ }
+
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reresultsadmin.php b/admin/report/fitandproper/reresultsadmin.php
new file mode 100644
index 00000000000..6d9437d6f29
--- /dev/null
+++ b/admin/report/fitandproper/reresultsadmin.php
@@ -0,0 +1,524 @@
+libdir.'/adminlib.php');
+require_once($CFG->libdir.'/csvlib.class.php');
+require_once 'reresultsadmin_upload_form.php';
+require_once 'reresultsadmin_report_form.php';
+
+if (!defined('MOODLE_INTERNAL')) {
+ die('Direct access to this script is forbidden.'); // It must be included from a Moodle page
+}
+
+$iid = optional_param('iid', null, PARAM_INT);
+$level = optional_param('level', null, PARAM_INT);
+
+require_login();
+
+require_capability('report/fitandproper:viewreresults', get_context_instance(CONTEXT_SYSTEM));
+
+$url = "$CFG->wwwroot/$CFG->admin/report/fitandproper/reresultsadmin.php";
+
+// Print the header.
+admin_externalpage_setup('reresultsadmin');
+echo $OUTPUT->header();
+
+echo $OUTPUT->heading(get_string('reresultsadmin_heading', 'report_fitandproper'));
+
+//$table->attributes = array('align'=>'center');
+$tablehead = array(get_string('reresultsadmin_tableheadsurname', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadtitle', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadinitials', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadid', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheademail', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadmobile', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadstatus', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadgroup', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadvenue', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadregistration', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadevent', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadexam', 'report_fitandproper'),
+ get_string('reresultsadmin_tableheadresult', 'report_fitandproper'),
+ );
+//var_dump($CFG);
+/*
+ * Handle the CSV file upload event
+ */
+$upload_form = new reresultsadmin_upload_form(null);
+
+$show_report = false;
+if($upload_form->is_cancelled())
+{
+ redirect($url);
+}
+elseif($data = $upload_form->get_data())
+{
+ $iid = csv_import_reader::get_new_iid('results');
+ $cir = new csv_import_reader($iid, 'results');
+
+ $content = $upload_form->get_file_content('csvfile');
+ $readcount = $cir->load_csv_content($content, 'UTF-8', 'comma');
+
+ $cir->close();
+ if($cir->get_error() != null)
+ {
+ print_error('csvloaderror', '', $url);
+ }else
+ {
+ /*
+ * If there is no error in the CSV file, display import report
+ */
+ $report = get_results_import_report($iid,$cir,$data->level);
+
+ display_results_import_report($report,$tablehead,$data->level,$readcount);
+
+ $links_form = new reresultsadmin_report_form(null,array('iid'=>$iid,'level'=>$data->level));
+
+ $links_form->display();
+ }
+ $show_report = true;
+}
+
+if($iid > 0 && $show_report == false)
+{
+ $links_form = new reresultsadmin_report_form(null);
+
+ if($links_form->is_cancelled())
+ {
+ redirect($url);
+ }elseif($data = $links_form->get_data())
+ {
+ /*
+ * Report accepted and now process the import
+ */
+ $cir = new csv_import_reader($iid, 'results');
+ $report = get_results_import_report($iid,$cir,$data->level);
+
+ do_reresults_import($report,$data->level);
+ $cir->close();
+ $cir->cleanup();
+
+ // Log.
+ add_to_log(SITEID, 'RE Exam Results', ": Upload", "report/fitandproper/reresultsadmin.php",'RE Exam Resulta');
+
+ redirect($url);
+ }
+}
+
+if($iid == null)
+{
+
+ $upload_form = new reresultsadmin_upload_form(null);
+
+ $upload_form->display();
+
+ /*
+ * Display results list table
+ */
+ echo $OUTPUT->box_start('reresultslist');
+
+ $results = $DB->get_records_sql('SELECT r.re_level_id,l.name,COUNT(r.id) FROM {re_exam_result} r INNER JOIN mdl_re_level l ON (r.re_level_id = l.id) WHERE r.deleted = 0 GROUP BY r.re_level_id,l.name ORDER BY l.name');
+
+ $level = 0;
+ $level_total = 0;
+
+ if(count($results) > 0)
+ {
+ foreach($results as $r)
+ {
+ $res = $DB->get_records('re_exam_result',array('deleted'=>0,'re_level_id'=>$r->re_level_id),'surname');
+ echo ''.$r->name.' ('.count($res).') ';
+
+ $table = new html_table();
+ $table->head = $tablehead;
+ foreach($res as $rs)
+ {
+ $row = new html_table_row(array($rs->surname,$rs->title,$rs->initials,$rs->id_number,$rs->email,$rs->mobile,$rs->status,
+ $rs->group_referer,$rs->venue,$rs->registration_ref,$rs->event_id,$rs->exam,$rs->result));
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ }
+ else
+ {
+ $table = new html_table();
+ $table->head = array('');
+ $row = new html_table_row(array(get_string('reresultsadmin_tablenorows', 'report_fitandproper')));
+ $row->attributes = array('class'=>'10');
+ $table->data[] = $row;
+ }
+
+ //echo html_writer::table($table);
+
+ echo $OUTPUT->box_end();
+
+ /*
+ * Display the CSV upload form
+ */
+}
+
+// Footer.
+echo $OUTPUT->footer();
+
+/**
+ * Function to get a report of the re exam results imports
+ * @param integer $iid ID of the uploaded CSV file
+ * @param object $cir The CSV file import class
+ * @param integer $level The id of the selected re level
+ * @return accociative array of the report
+ */
+function get_results_import_report($iid,$cir,$level)
+{
+ global $DB;
+
+ $arr_add = array();
+ $arr_update = array();
+ $arr_delete = array();
+ $arr_unchange = array();
+ $arr_ignore = array();
+
+ //get list from database;
+ $results = $DB->get_records('re_exam_result',array('deleted'=>0,'re_level_id'=>$level));
+
+ $cir->init();
+ while ($line = $cir->next())
+ {
+ $exam_id = check_exam($line,$level);
+ if(!$exam_id)
+ {
+ $arr_ignore[] = array('line'=>$line,'errors'=>'Exam name not found in this RE Level');
+ continue;
+ }else
+ {
+ $line[13] = $exam_id;
+ }
+
+ $user_id = check_user($line,$level);
+ if(!$user_id)
+ {
+ $arr_ignore[] = array('line'=>$line,'errors'=>'User not found on system');
+ continue;
+ }else
+ {
+ $line[14] = $user_id;
+ }
+
+ if(empty($line[12]))
+ {
+ $arr_ignore[] = array('line'=>$line,'errors'=>'No result specified');
+ continue;
+ }
+
+ $in_db = false;
+ $x=1;
+ foreach($results as $r)
+ {
+ //get the exam name
+ //$exam = $DB->get_record('re_exam',array('id'=>$results->))
+
+ if((strtolower($line[0]) == strtolower($r->surname)) && (strtolower($line[3]) == strtolower($r->id_number)) && (strtolower($line[11]) == strtolower($r->exam)))
+ {
+ $line['db_id'] = $r->id;
+ $in_db = true;
+ $results[$r->id]->in_csv = true;
+
+ //check if qualification is updated or changed
+ $unchange = true;
+
+ if(strtolower($line[1]) != strtolower($r->title)) $unchange = false;
+ if(strtolower($line[2]) != strtolower($r->initials)) $unchange = false;
+ if(strtolower($line[4]) != strtolower($r->email)) $unchange = false;
+ if(strtolower($line[5]) != strtolower($r->mobile)) $unchange = false;
+ if(strtolower($line[6]) != strtolower($r->status)) $unchange = false;
+ if(strtolower($line[7]) != strtolower($r->group_referer)) $unchange = false;
+ if(strtolower($line[8]) != strtolower($r->venue)) $unchange = false;
+ if(strtolower($line[9]) != strtolower($r->registration_ref)) $unchange = false;
+ if(strtolower($line[10]) != strtolower($r->event_id)) $unchange = false;
+ if(strtolower($line[12]) != strtolower($r->result)) $unchange = false;
+
+ if($unchange)
+ {
+ $arr_unchange[$line[3]] = $line;
+ }else
+ {
+ $arr_update[$line[3]] = array('u'=>$line,'c'=>$r);
+ }
+ }
+ $x++;
+ }
+
+ //this is a new entry
+ if($in_db == false)
+ {
+ $arr_add[$line[3]] = $line;
+ }
+ }
+
+ /*
+ * Check which entries in the database to delete
+ */
+// foreach($results as $r)
+// {
+// if(!isset($r->in_csv) || $r->in_csv == false)
+// {
+// $arr_delete[] = $r;
+// }
+// }
+
+ /*
+ * return an array of the report rows within their repective actions eg.add/update/delete/unchange/ingore
+ */
+ return array('add'=>$arr_add,'update'=>$arr_update,'delete'=>$arr_delete,'unchange'=>$arr_unchange,'ignore'=>$arr_ignore);
+}
+
+/**
+ * Function to validate a the exam name in a CSV file
+ * @param array The row array
+ * @return mixed ID of exam or false if exam does not exist
+ */
+function check_exam($row,$level)
+{
+ global $DB;
+
+ $exam = $DB->get_record('re_exam',array('name'=>$row[11],'deleted'=>0));
+
+ if($exam)
+ {
+ return $exam->id;
+ }else
+ {
+ return false;
+ }
+}
+
+/**
+ * Function to check if user exist in a CSV file
+ * @param array The row array
+ * @param $level integer The level ID
+ * @return mixed ID of user or false if exam does not exist
+ */
+function check_user($row,$level)
+{
+ global $DB;
+
+ $user = $DB->get_record_select('user','lastname = ? AND idnumber = ?',array($row[0],$row[3]));
+
+ if($user)
+ {
+ return $user->id;
+ }else
+ {
+ return false;
+ }
+}
+
+/**
+ * Function to display the re exam results imports
+ * @param array The report in an array
+ */
+function display_results_import_report($report,$tablehead,$level_id,$count)
+{
+ global $DB;
+
+ $level = $DB->get_record('re_level',array('id'=>$level_id));
+
+ print ''.$level->name.' RE Exam Results processed: '.$count;
+ /*
+ * Display add
+ */
+ echo ''.get_string('reresultsadmin_report_add', 'report_fitandproper').': '.count($report['add']).' ';
+ if(count($report['add']) > 0)
+ {
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ foreach($report['add'] as $q)
+ {
+ $row = new html_table_row(array($q[0],$q[1],$q[2],$q[3],$q[4],
+ $q[5],$q[6],$q[7],$q[8],$q[9],$q[10],$q[11],$q[12]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display update
+ */
+ echo ''.get_string('reresultsadmin_report_update', 'report_fitandproper').': '.count($report['update']).' ';
+ if(count($report['update']) > 0)
+ {
+ $table = new html_table();
+
+ $head = array('');
+ $head = array_merge($head,$tablehead);
+ $table->head = $head;
+
+ foreach($report['update'] as $q)
+ {
+ $row = new html_table_row(array(get_string('reresultsadmin_report_update_current', 'report_fitandproper'),$q['c']->surname,$q['c']->title,$q['c']->initials,$q['c']->id_number,$q['c']->email,
+ $q['c']->mobile,$q['c']->status,$q['c']->group_referer,$q['c']->venue,$q['c']->registration_ref,$q['c']->event_id,$q['c']->exam,$q['c']->result));
+ $table->data[] = $row;
+
+ $row = new html_table_row(array(get_string('reresultsadmin_report_update_update', 'report_fitandproper'),$q['u'][0],$q['u'][1],$q['u'][2],$q['u'][3],$q['u'][4],
+ $q['u'][5],$q['u'][6],$q['u'][7],$q['u'][8],$q['u'][9],$q['u'][10],$q['u'][11],$q['u'][12]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display delete
+ * delete is a class object
+ */
+ echo ''.get_string('reresultsadmin_report_delete', 'report_fitandproper').': '.count($report['delete']).' ';
+ if(count($report['delete']) > 0)
+ {
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ foreach($report['delete'] as $q)
+ {
+ $row = new html_table_row(array($q->surname,$q->title,$q->initials,$q->id_number,$q->email,
+ $q->mobile,$q->status,$q->group_referer,$q->venue,$q->registration_ref,$q->event_id,$q->exam,$q->result));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display unchanged
+ */
+ echo ''.get_string('reresultsadmin_report_unchange', 'report_fitandproper').': '.count($report['unchange']).' ';
+ if(count($report['unchange']) > 0)
+ {
+ $table = new html_table();
+ $table->head = $tablehead;
+
+ foreach($report['unchange'] as $q)
+ {
+ $row = new html_table_row(array($q[0],$q[1],$q[2],$q[3],$q[4],
+ $q[5],$q[6],$q[7],$q[8],$q[9],$q[10],$q[11],$q[12]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+ /*
+ * Display ignored
+ */
+ echo ''.get_string('reresultsadmin_report_ignore', 'report_fitandproper').': '.count($report['ignore']).' ';
+ if(count($report['ignore']) > 0)
+ {
+ $head = array(get_string('reresultsadmin_report_ignore_error', 'report_fitandproper'));
+ $head = array_merge($head,$tablehead);
+ $table = new html_table();
+ $table->head = $head;
+
+ foreach($report['ignore'] as $q)
+ {
+ $errors = $q['errors'];
+
+ $row = new html_table_row(array($errors,$q['line'][0],$q['line'][1],$q['line'][2],$q['line'][3],$q['line'][4],
+ $q['line'][5],$q['line'][6],$q['line'][7],$q['line'][8],$q['line'][9],$q['line'][10],$q['line'][11],$q['line'][12]));
+
+ $table->data[] = $row;
+ }
+ echo html_writer::table($table);
+ }
+
+}
+
+/**
+ * Function that does the actual import to database
+ * @param array The report data in an array
+ * @param integer The id of the selected re level
+ */
+function do_reresults_import($report,$level)
+{
+ global $DB;
+
+ /*
+ * Proccess the added qualifications
+ */
+ foreach($report['add'] as $r)
+ {
+ $record = new stdClass();
+ $record->surname = $r[0];
+ $record->title = $r[1];
+ $record->initials = $r[2];
+ $record->id_number = $r[3];
+ $record->email = $r[4];
+ $record->mobile = $r[5];
+ $record->status = $r[6];
+ $record->group_referer = $r[7];
+ $record->venue = $r[8];
+ $record->registration_ref = $r[9];
+ $record->event_id = $r[10];
+ $record->exam = $r[11];
+ $record->result = $r[12];
+ $record->timecreated = time();
+ $record->timemodified = time();
+ $record->re_level_id = $level;
+ $record->re_exam_id = $r[13];
+ $record->moodle_user_id = $r[14];
+
+ $DB->insert_record('re_exam_result',$record,false);
+ unset($record);
+ }
+
+ /*
+ * Proccess the updated qualifications
+ */
+ foreach($report['update'] as $r)
+ {
+ $record = new stdClass();
+ $record->surname = $r['u'][0];
+ $record->title = $r['u'][1];
+ $record->initials = $r['u'][2];
+ $record->id_number = $r['u'][3];
+ $record->email = $r['u'][4];
+ $record->mobile = $r['u'][5];
+ $record->status = $r['u'][6];
+ $record->group_referer = $r['u'][7];
+ $record->venue = $r['u'][8];
+ $record->registration_ref = $r['u'][9];
+ $record->event_id = $r['u'][10];
+ $record->exam = $r['u'][11];
+ $record->result = $r['u'][12];
+ $record->timecreated = time();
+ $record->timemodified = time();
+ $record->re_level_id = $level;
+ $record->re_exam_id = $r['u'][13];
+ $record->moodle_user_id = $r['u'][14];
+
+ $DB->insert_record('re_exam_result',$record,false);
+
+ //delete old record
+ $record = new stdClass();
+ $record->id = $r['u']['db_id'];
+ $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('re_exam_result',$record);
+ }
+
+ /*
+ * Proccess the deleted qualifications
+ */
+ foreach($report['delete'] as $r)
+ {
+ $record = new stdClass();
+ $record->id = $r->id;
+// $record->deleted = 1;
+ $record->timemodified = time();
+ $DB->update_record('re_exam_result',$record);
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reresultsadmin_report_form.php b/admin/report/fitandproper/reresultsadmin_report_form.php
new file mode 100644
index 00000000000..bcd84d3a82a
--- /dev/null
+++ b/admin/report/fitandproper/reresultsadmin_report_form.php
@@ -0,0 +1,24 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the RE exam results CSV file upload form
+ */
+class reresultsadmin_report_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ $iid = $this->_customdata['iid'];
+ $level = $this->_customdata['level'];
+
+ $mform->addElement('hidden', 'iid', $iid);
+ $mform->addElement('hidden', 'level', $level);
+
+ $this->add_action_buttons(true,get_string('reresultsadmin_report_accept', 'report_fitandproper'));
+
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/reresultsadmin_upload_form.php b/admin/report/fitandproper/reresultsadmin_upload_form.php
new file mode 100644
index 00000000000..fcae18fb359
--- /dev/null
+++ b/admin/report/fitandproper/reresultsadmin_upload_form.php
@@ -0,0 +1,50 @@
+libdir.'/formslib.php');
+
+/**
+ * a Class to diplay the RE results CSV file upload form
+ */
+class reresultsadmin_upload_form extends moodleform {
+
+ function definition()
+ {
+ global $DB;
+
+ $mform = $this->_form;
+
+ //$op = $this->_customdata['op'];
+
+ //get list of re levels
+ $re_levels = $DB->get_records('re_level',array('enabled'=>1,'deleted'=>0),'name','id,name');
+ $level_list = array(0=>get_string('reresultsadmin_formselect', 'report_fitandproper'));
+ foreach($re_levels as $level)
+ {
+ $level_list[$level->id] = $level->name;
+ }
+
+ $mform->addElement('html', '');
+
+ $mform->addElement('filepicker', 'csvfile', get_string('reresultsadmin_formfile', 'report_fitandproper'), null, array('maxbytes' => 8000000, 'accepted_types' => 'csv'));
+ //$mform->addElement('file', 'csvfile', get_string('qualificationadmin_formfile', 'report_fitandproper'));
+ $mform->addRule('csvfile', null, 'required');
+
+ $mform->addElement('select', 'level', get_string('reresultsadmin_formlevel', 'report_fitandproper'),$level_list);
+ $mform->addRule('level', null, 'required');
+ //$mform->addElement('hidden', 'id');
+
+ $this->add_action_buttons(false,get_string('reresultsadmin_formupload', 'report_fitandproper'));
+
+ }
+
+ function validation($data)
+ {
+ $errors = array();
+
+ if($data['level'] == 0)
+ {
+ $errors['level'] = get_string('reresultsadmin_formselect_error', 'report_fitandproper');
+ }
+
+ return $errors;
+ }
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/settings.php b/admin/report/fitandproper/settings.php
new file mode 100644
index 00000000000..41c7ec30fc8
--- /dev/null
+++ b/admin/report/fitandproper/settings.php
@@ -0,0 +1,65 @@
+add('reports', new admin_externalpage('fiascategoryadmin', get_string('faiscategoryadmin', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/faiscategoryadmin.php",'report/fitandproper:viewfaiscategories'));
+
+/*
+ * Intitutions admin
+ */
+$ADMIN->add('reports', new admin_externalpage('institutionadmin', get_string('institutionadmin', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/institutionadmin.php",'report/fitandproper:viewinstitutions'));
+
+/*
+ * Qualifications admin
+ */
+$ADMIN->add('reports', new admin_externalpage('qualificationadmin', get_string('qualificationadmin', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationadmin.php",'report/fitandproper:viewqualifications'));
+
+/*
+ * CPD Activities admin
+ */
+$ADMIN->add('reports', new admin_externalpage('cpdactivityadmin', get_string('cpdactivityadmin', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivityadmin.php",'report/fitandproper:viewcpdactivities'));
+
+/*
+ * Qualification maintenance
+ */
+$userid = optional_param('userid',null,PARAM_TEXT);
+$partyid = optional_param('partyid',null,PARAM_TEXT);
+$ADMIN->add('reports', new admin_externalpage('qualificationmaintenance', get_string('qualificationmaintenance', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmaintenance.php?userid=".$userid,'report/fitandproper:viewqualificationmaintenance',true));
+
+/*
+ * Qualification manager
+ */
+$ADMIN->add('reports', new admin_externalpage('qualificationmanager', get_string('qualificationmanager', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/qualificationmanager.php",'report/fitandproper:viewqualificationmanager',true));
+
+/*
+ * CPD Activity maintenance
+ */
+$ADMIN->add('reports', new admin_externalpage('cpdactivitymaintenance', get_string('cpdactivitymaintenance', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymaintenance.php?userid=".$userid,'report/fitandproper:viewcpdactivitymaintenance',true));
+
+/*
+ * CPD Activity manager
+ */
+$ADMIN->add('reports', new admin_externalpage('cpdactivitymanager', get_string('cpdactivitymanager', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/cpdactivitymanager.php",'report/fitandproper:viewcpdactivitymanager',true));
+
+/*
+ * Reexam Results maintenance
+ */
+$ADMIN->add('reports', new admin_externalpage('reexamresultsmaintenance', get_string('reexamresultsmaintenance', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmaintenance.php?partyid=".$partyid,'report/fitandproper:viewreexamresultsmaintenance',true));
+
+/*
+ * Reexam Results manager
+ */
+$ADMIN->add('reports', new admin_externalpage('reexamresultsmanager', get_string('reexamresultsmanager', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamresultsmanager.php?partyid=".$partyid,'report/fitandproper:viewreexamresultsmanager',true));
+
+/*
+ * RE Exams
+ */
+$ADMIN->add('reports', new admin_externalpage('reexamadmin', get_string('reexamadmin', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/reexamadmin.php",'report/fitandproper:viewreexams'));
+
+/*
+ * RE Exams Results
+ */
+$ADMIN->add('reports', new admin_externalpage('reresultsadmin', get_string('reresultsadmin', 'report_fitandproper'), "$CFG->wwwroot/$CFG->admin/report/fitandproper/reresultsadmin.php",'report/fitandproper:viewreresults'));
\ No newline at end of file
diff --git a/admin/report/fitandproper/styles.css b/admin/report/fitandproper/styles.css
new file mode 100644
index 00000000000..cbbe18908f4
--- /dev/null
+++ b/admin/report/fitandproper/styles.css
@@ -0,0 +1,142 @@
+#intro
+{
+ text-align: center;
+}
+
+#faisaddcat
+{
+ text-align: center;
+}
+
+#faiscategorylist
+{
+ border: 1px solid black;
+}
+
+#faiscategorylist th
+{
+ border-bottom: 1px solid black;
+ background-color: #E1E1DF;
+}
+
+.subcatlist
+{
+ padding-left: 40px;
+}
+
+.editicon
+{
+ margin-left: 10px;
+}
+
+.faiseditform
+{
+
+
+}
+
+.mform #id_submitbutton
+{
+ margin-left: 16%;
+ float: left;
+}
+
+.mform .fdescription
+{
+ float: left;
+ margin-left: 16%;
+}
+
+.faiseditformheader
+{
+ margin-left: 16%;
+}
+
+#faiseditreport
+{
+ width: 500px;
+ border: 1px solid black;
+ padding: 10px
+}
+
+.reportlist
+{
+ width: 490px;
+ border: 1px solid black;
+}
+
+.reportlist th
+{
+ border-bottom: 1px solid black;
+ background-color: #E1E1DF;
+ text-align: left;
+}
+
+.faiscategorydisabled
+{
+ color: #999999;
+}
+
+.leftborder
+{
+ border-left: 1px solid black;
+}
+
+.filterset
+{
+ border: 1px solid black;
+}
+
+.filterset legend
+{
+ padding: 5px;
+ font-weight: bold;
+}
+
+.institutionlist
+{
+ text-align: center;
+}
+
+.cpdactivitylist
+{
+ text-align: center;
+}
+
+.qualificationmaintenancelist
+{
+ text-align: center;
+}
+
+.cpdactivitymaintenancelist
+{
+ text-align: center;
+}
+
+.reexamresultsmaintenancelist
+{
+ text-align: center;
+}
+
+.reresultslist {
+ text-align: center;
+ overflow: auto;
+}
+
+.qualificationlist {
+ text-align: center;
+ overflow: auto;
+}
+
+#reexamadd
+{
+ text-align: center;
+ width: 300px;
+ margin: 0 auto;
+}
+
+#frmreexamadd
+{
+ float:left;
+ padding-left: 10px;
+}
\ No newline at end of file
diff --git a/admin/report/fitandproper/version.php b/admin/report/fitandproper/version.php
new file mode 100644
index 00000000000..0e867584b61
--- /dev/null
+++ b/admin/report/fitandproper/version.php
@@ -0,0 +1,2 @@
+version = 2011040126;
\ No newline at end of file