Skip to content

Commit

Permalink
Merge pull request #25 from sugarcrm/add-to-gradebook
Browse files Browse the repository at this point in the history
Fixes issue #15 - create record in gradebook for new students
  • Loading branch information
mmarum-sugarcrm authored Feb 9, 2018
2 parents 7428024 + 0ad5ac6 commit be516e8
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 5 deletions.
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
},
"autoload": {
"psr-4": {
"Sugarcrm\\ProfessorM\\": "package/"
"Sugarcrm\\ProfessorM\\": "package/",
"Sugarcrm\\Sugarcrm\\custom\\": [
"package/src/custom/"
]
}
}
}
79 changes: 79 additions & 0 deletions docs/Gradebook.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Gradebook Integration

Professor M needs to do more than just track basic information about his students; he needs to track their grades as
well. He has decided to integrate Sugar with an external gradebook app. When a new student is created in Sugar, a new
record should be automatically created in the gradebook app.

## About the Gradebook App

The gradebook app is being simulated by the files inside of
[package/src/custom/gradebook_fake](../package/src/custom/gradebook_fake). If the gradebook app were real,
it would be implemented outside of Sugar as a separate system.

The simulated gradebook app does not currently store any data. It simulates responses that would be returned from an
external gradebook app.

## Setting up the cron scheduler

The implementation requires the Sugar Schedulers to be running. In order for the Schedulers to run, a process needs to
be running on the server to initiate the Schedulers. The Scheduler is set up automatically for On-Demand Instances.
Admins of on-premises installations of Sugar will need to set up a cron scheduler manually. See the Setting up Cron
Scheduler section of the
[Sugar Developer Guide](http://support.sugarcrm.com/SmartLinks/Administration_Guide/System/Schedulers/index.html#Setting_up_Cron_Scheduler)
for details.

Tip: if you see errors when running cron, you may need to update the command in the crontab file to have the full path
to your php. For example:
`* * * * * cd /Applications/MAMP/htdocs/profm711; /Applications/MAMP/bin/php/php7.1.1/bin/php -f cron.php > /dev/null 2>&1`

## Implementation Technique

An after_save logic hook that puts a job on the Sugar Job Queue was created based on the example in the
[Sugar Developer Guide](http://support.sugarcrm.com/SmartLinks/Developer_Guide/Architecture/Job_Queue/Jobs/Queuing_Logic_Hook_Actions).

## Implementation Details

An after_save logic hook is defined in
[add_to_gradebook.profm.php](../package/src/custom/Extension/modules/Contacts/Ext/LogicHooks/add_to_gradebook.profm.php).

Whenever a new record is created in the Contacts (Students) module, the after_save logic hook will be triggered. The
logic hook indicates that the `AddStudentToGradebook()` function in
[Students_Gradebook.php](../package/src/custom/modules/Contacts/Students_Gradebook.php) should be called.

The `AddStudentToGradebook()` function begins by checking if the record is new or just an update. If the record is new,
it will create a new job and add it to the Sugar Job Queue.

The next time the Sugar Job Queue is executed, the new job will be run. The job calls the `AddStudentToGradebookJob()`
function inside of
[AddStudentToGradebookJob.php](../package/src/custom/Extension/modules/Schedulers/Ext/ScheduledTasks/AddStudentToGradebookJob.php).
This function is what calls our fake gradebook integration's
[RecordManager](../package/src/custom/gradebook_fake/RecordManager.php).

The [RecordManager](../package/src/custom/gradebook_fake/RecordManager.php) doesn't actually create a record. It simply
simulates a response. [RecordManager](../package/src/custom/gradebook_fake/RecordManager.php)'s createStudentRecord()
function will return true unless the email address `[email protected]` is used, in which case an exception will be
thrown.

Note that this implementation uses a job in the Sugar Job Queue to call the gradebook app instead of calling the
gradebook app directly from the logic hook. We chose this implementation so that the saving of new Student records would
not be slowed down by the process of creating a new record in a potentially slow gradebook app. If we made the call to
the gradebook app directly from the logic hook, the record would not finish saving until a response was returned from
the gradebook app.

## Trying the Use Case

Before trying the use case, be sure you have set up the cron scheduler.

Navigate to the Students module and create a new student record. If everything works correctly, you will NOT see any
errors in sugarcrm.log.

If you want to simulate an error in the gradebook app, navigate to the Students module and create a new student record
with the e-mail address `[email protected]`. An error similar to the following will be displayed in sugarcrm.log:

```
Wed Feb 7 17:17:02 2018 [61178][1][FATAL] Job 92d9c8dc-0c2a-11e8-9f94-7200080cd7d0 (Add New Student to Gradebook Job - ) failed in CRON run
```

You can browse the `job_queue table` of the database to see a list of all jobs executed. The name of the job created
by this implementation is `Add New Student to Gradebook Job`. Regardless of whether the job succeeds or fails,
it will be listed in this table.
5 changes: 2 additions & 3 deletions docs/UseCases.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,5 @@ The Professor M School uses Sugar for the following high level use cases:

## Implemented Use Cases

[Student Health Tracking](StudentHealthTracking.md)


- [Student Health Tracking](StudentHealthTracking.md)
- [Gradebook Integration](Gradebook.md)
2 changes: 1 addition & 1 deletion package/src/custom/Extension/modules/Accounts/Ext/Vardefs/sugarfield_status_c.php
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
// created: 2017-08-07 20:21:33
// created: 2018-01-31 08:41:42
$dictionary['Account']['fields']['status_c']['labelValue']='Status';
$dictionary['Account']['fields']['status_c']['dependency']='';
$dictionary['Account']['fields']['status_c']['visibility_grid']='';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

$hook_array['after_save'][] = Array(
//Processing index. For sorting the array.
1,

//Label. A string value to identify the hook.
'after_save add student to gradebook',

//The PHP file where the class is located.
'custom/modules/Contacts/Students_Gradebook.php',

//The class the method is in.
'Students_Gradebook',

//The method to call.
'AddStudentToGradebook'
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

use Sugarcrm\Sugarcrm\custom\gradebook_fake\RecordManager;

/**
* This function defines the job that adds a new student to the GradebookFake app
* @param $job Information about the job. $job->data should be the id for the new Student (contact) record
* @return bool true if a record was successfully created in the GradebookFake app
*/
function AddStudentToGradebookJob($job)
{
if (!empty($job->data))
{
$bean = BeanFactory::getBean('Contacts', $job->data);

//Call the external GradebookFake app to create a new record in it
$rm = new RecordManager();
return $rm->createStudentRecord($bean->email1, $bean->first_name, $bean->last_name);
}

return false;
}
28 changes: 28 additions & 0 deletions package/src/custom/gradebook_fake/RecordManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Sugarcrm\Sugarcrm\custom\gradebook_fake;

/**
* Class RecordManager
* @package GradebookFake
* This class manages the records for GradebookFake.
* No records are actually saved!
*/
class RecordManager
{
/**
* This function pretends to create a student record in GradebookFake
* @param $email
* @param $firstName
* @param $lastName
* @return bool true if the record was created in GradebookFake
* @throws \Exception if the email address [email protected] is used
*/
public function createStudentRecord($email, $firstName, $lastName)
{
if ($email === '[email protected]'){
throw new \Exception("An error was forced because the email address [email protected] was used.");
}
return true;
}
}
44 changes: 44 additions & 0 deletions package/src/custom/modules/Contacts/Students_Gradebook.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

/**
* Class Students_Gradebook
* Handles creating a job for the Sugar Job Queue that adds a new student to the GradebookFake app
*/
class Students_Gradebook
{
/**
* Creates a job that calls a function to add a new student to the GradebookFake app. Adds the job to the Sugar
* Job Queue. The job will be executed the next time the Queue is run.
* @param $bean The bean for the Student (Contact) record
* @param $event The current event
* @param $arguments Additional information related to the event
*/
function AddStudentToGradebook(&$bean, $event, $arguments)
{
//Check if this is a new student record or just an update to an existing record
if(!$arguments['isUpdate']){

require_once('include/SugarQueue/SugarJobQueue.php');

//create the new job
$job = new SchedulersJob();
//job name
$job->name = "Add New Student to Gradebook Job";
//data we are passing to the job
$job->data = $bean->id;
//function to call
$job->target = "function::AddStudentToGradebookJob";

global $current_user;
//set the user the job runs as
$job->assigned_user_id = $current_user->id;

//push into the queue to run
$jq = new SugarJobQueue();
$jobid = $jq->submitJob($job);
}

}
}
30 changes: 30 additions & 0 deletions tests/phpunit/src/custom/gradebook_fake/RecordManagerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);

use Sugarcrm\Sugarcrm\custom\gradebook_fake\RecordManager;
use PHPUnit\Framework\TestCase;

/**
* Class RecordManagerTest
* Tests the RecordManager for the GradebookFake app
*/
class RecordManagerTest extends TestCase
{
/**
* Check that when valid params are sent to createStudentRecord, true is returned
*/
public function testRecordManagerValidParams(){
$rm = new RecordManager();
$this->assertTrue($rm->createStudentRecord('[email protected]', 'Lauren', 'Sample'));
}

/**
* Check that when the email address [email protected] is used as a param for createStudentRecord, an
* exception is thrown
*/
public function testRecordManagerForceException(){
$rm = new RecordManager();
$this -> expectException(Exception::class);
$rm->createStudentRecord('[email protected]', 'Lauren', 'Sample');
}
}

0 comments on commit be516e8

Please sign in to comment.