© 2018 Capita Business Services Ltd. All rights reserved.

Capita Education Software Solutions is a trading name of Capita Business Services Ltd. Our Registered office is 30 Berners Street, London, W1T 3LR and our registered number is 02299747. Further information about Capita plc can be found in our legal statement.

Local API - Session Attendance

Introduction

This application is designed to show the principles of coding against SIMS Partner Interfaces. The UI is designed to facilitate the demo rather than to suggest good UI practice. The interfaces, particularly with regard to XML, are simply sufficient to show principle rather than elegance.

This document adds a commentary to the downloadable sample code

Legal Specifications

The download and use of the sample code are subject to terms and conditions of use and require the distributor to register as a SIMS Partner and be subject to any charges which result from that partnership. Sample code may not be redistributed as code. However, permission is given to share the URL of this document and for the subsequent reader to download the code themselves subject to the same terms and conditions. This enables ESS to update the code samples and reduces the likelihood of bug propagation.

Other Requirements

To compile binaries, a copy of Visual Studio 2017 or later is required with the appropriate components installed for C# and Windows Command Line Applications.

A copy of SIMS 7 (all components) is required to be installed on the machine at the latest available version.

A copy of training data is required to ensure DPA / GDPR compliance. If you do not have this available, please contact us. (Charges apply).

The Applications

  • Solution ‘Sample Partner Application’ (4 Projects)
    • Partner World
    • Read Attendance
    • Write Attendance

Recommended architecture

Our example has 2 console applications:

  • ReadAttendance
  • WriteAttendance

Both applications read or write one student’s attendance marks for a given day. Whilst typically the Read application works on any day, the Write application is likely to fail if users try to write marks back in a holiday or other inappropriate scenarios.

The applications join up 2 services:

  • Partner World which will contain all the partner IP and functionality.
    • Get a student
    • Get a mark to save in SIMS
  • SIMS Interface
    • Get Students for the partner Application
    • Write marks from the partner system back in to SIMS.

Ideally the data moving between the 2 services is via a portable format such as XML.

Read

if (SIMSInterface.LoginHelper.SIMSlogin(Server, Database, User, Password))
{      // Get Students      
    XmlDocument Students = SIMSInterface.Students.GetCurrentStudents();
    // Save Students to Partner System      
    PartnerWorld.AttendanceInterface.SaveStudentData(Students);
    // Get Attendance codes      
    XmlDocument AttendanceCodes = SIMSInterface.Attendance.GetAttendanceCodes();
    // Save Attendance Codes to partner system     
    PartnerWorld.AttendanceInterface.SaveAttendanceMarks(AttendanceCodes);
    // Get some Marks                                         
    Console.WriteLine(SIMSInterface.Attendance.GetAttendanceRead(
    PartnerWorld.AttendanceInterface.AttendanceDate,
    PartnerWorld.AttendanceInterface.StudentID).InnerXml);
}

Commentary

  • First log in to SIMS.
  • The Get Students is used to find a valid student ID for the read / write.
  • Save Students to the Partner World sets a student id for later use.
  • Get Attendance Codes loads the codes from SIMS – see module 6 for an example.
  • Save attendance codes to Partner World makes sense on the assumption that marks will need to be interpreted.
  • GetAttendanceRead pulls back the day of attendance marks for the specified student.

Write

As above but adds

// Add some Marks
SIMSInterface.Attendance.ClearMarks();
// AM
SIMSInterface.Attendance.AddAMMark(PartnerWorld.AttendanceInterface.StudentID, PartnerWorld.AttendanceInterface.AttendanceDate, PartnerWorld.AttendanceInterface.AttendanceCode, 1, "Good Morning");
// PM
SIMSInterface.Attendance.AddPMMark(PartnerWorld.AttendanceInterface.StudentID, PartnerWorld.AttendanceInterface.AttendanceDate, PartnerWorld.AttendanceInterface.AttendanceCode, 1, "Good Afternoon");
// Save
string Errors = SIMSInterface.Attendance.SaveSessionMarks();

Commentary

  • The class keeps a list of session marks formatted as XML to save.
  • Clear Marks clears the list
  • Add – adds a new mark AM or PM
  • The Partner Attendance Code Save sets the default mark to save.
  • Save Session Marks will try to save the marks

Strong Names.

SIMS 7 is strong named and hence when SIMS is updated a partner application is likely to fail strong name checks.

SIMSInterface.SIMSDllResolution.AddSIMSDllResolution();

Adding the line above in to the main application is generally all that is needed to resolve dll changes. However, this takes effect once the current function is exited. Hence the guidance to call SIMS functionality from any other function but not ‘main'.

This code would need to be modified for web applications.

Partners are not licensed to re-distribute SIMS Binaries but this is actually a benefit to partners. Where partners have accidentally shipped binaries with their application, SIMS upgrades usually break their application. Use Copy Local = False in the IDE for best results.

Single Threaded Code Model

SIMS APIs are not typically stateless unless advised to the contrary on a per API basis. Odd errors occur if SIMS APIs are used in a multi-threaded environment and data corruption via thread bleed may occur when used in anger. Typically, developers do not see this issue during coding.

An understanding of SIMS Logins is assumed from the SIMS Write Back Core Module.

Concepts and Details

 Introduction

This application is designed to show the principles of coding against SIMS Partner Interfaces. The UI is designed to facilitate the demo rather than to suggest good UI practice.  The interfaces, particularly with regard to XML, are simply sufficient to show principle rather than elegance.

Login

An understanding of SIMS Logins is assumed from the SIMS Write Back Core Module.


//Pick a date time as appropriate, for example:
DateTime attendanceDate;
AttendanceDate = Datetime.Now;
//Pick an Attendance Session 
//Decide morning or afternoon, for example:
	String Session = “PM”;
	If (Morning())
		Session = “AM”;
//Load the set of Attendance Codes
SIMS.Processes.TPAttendanceRead ATR = new SIMS.Processes.TPAttendanceRead();
// XML Document needed to get the codes
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
// This is the actual call to get the codes
doc.InnerXml = ATR.GetXmlAttendanceCodes();

All that remains is to extract the codes from the xml structure.

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<AttendanceCodes>
  <AttendanceCode>
    <AttendanceCodeID>27</AttendanceCodeID>
    <Code>-</Code>
    <Description>All should attend / No mark recorded</Description>
    <PhysicalMappingID>5</PhysicalMappingID>
    <PhysicalMappingDescription>No mark for session</PhysicalMappingDescription>
    <StatisticalMappingID>6</StatisticalMappingID>
    <StatisticalMappingDescription>No  mark</StatisticalMappingDescription>
  </AttendanceCode>
  <AttendanceCode>
    <AttendanceCodeID>24</AttendanceCodeID>
    <Code>X</Code>
    <Description> DfES X: Non-compulsory school age absence</Description>
    <PhysicalMappingID>3</PhysicalMappingID>
    <PhysicalMappingDescription>Out for whole session</PhysicalMappingDescription>
    <StatisticalMappingID>5</StatisticalMappingID>
    <StatisticalMappingDescription>Attendance not required</StatisticalMappingDescription>
  </AttendanceCode>
</AttendanceCodes>

 

Loading the set of registration groups

 

SIMS.Processes.TPGroupManagement
tpgm = new SIMS.Processes.TPGroupManagement();
// We need to have an XML Doc for the call
System.Xml.XmlDocument
doc = new System.Xml.XmlDocument();
// Get the set of reg groups
doc.InnerXml = tpgm.GetXmlGroups(attendanceDate, "RegGrp");

All that then remains is to extract the groups from the XML.

<?xml version="1.0" encoding="iso-8859-1"standalone="yes"?>
<Groups>
  <Group>
    <BaseGroupID>381</BaseGroupID>
    <BaseGroupTypeID>22</BaseGroupTypeID>
    <Code>J</Code>
    <Description>J</Description>
    <ShortName>J</ShortName>
    <PromoteToGroupID>381</PromoteToGroupID>
    <StartDate />
    <EndDate />
    <IsActive>A</IsActive>
  </Group>
</Groups>
 

Loading the Students in the Registration Group

SIMS.Processes.TPGroupManagement
tpgm = new SI MS.Processes.TPGroupManagement();
// We need an Xml document for the call
System.Xml.XmlDocument
doc = new System.Xml.XmlDocument();
string group2get = "381";  // Base Group ID from the above
// Create the xml message to request all the students in the group
System.Xml.XmlDocument group2getXML = new System.Xml.XmlDocument();
group2getXML.InnerXml = "<BaseGroups><BaseGroupID>"+ group2get + "</BaseGroupID></BaseGroups>";
// Call Get memberships to return the
student ids.
doc.InnerXml = tpgm.GetXmlMemberships(attendanceDate,group2getXML);

This one is a little more difficult because we need to form an XML query for the required base group.  The attendance date should be used to return group members for the correct date.

This returns a set of members

<?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
<Memberships>
  <Membership>
    <BaseGroupID>387</BaseGroupID>
    <PersonD>6347</PersonD>
    <StartDate>2007-09-03T00:00:00</StartDate>
    <EndDate>2008-09-01T23:59:00</EndDate>  </Membership>
  <Membership>
    <BaseGroupID>387</BaseGroupID>
    <PersonD>6355</PersonD>
    <StartDate>2007-09-03T00:00:00</StartDate>
    <EndDate>2008-09-01T23:59:00</EndDate>
  </Membership>
</Memberships>

Translating Student ID’s into something we can display

// Call the GetXmlStudents method to load the student.
SIMS.Processes.TPPersonStudent tpps = new SIMS.Processes.TPPersonStudent();
// We need an XmlDocument for later parsing
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
doc.InnerXml = tpps.GetXmlStudents(studentID);

 This call gets the basic student information for the student whose ID is ‘StudentID’ as follows:

 

<StudentExtendeds>
  <Student>
    <PersonID>2447</PersonID>
    <Forename>Ben</Forename>
    <Surname>Abbot</Surname>
    <ChosenName />
    <MiddleName />
    <LegalSurname>Abbot</LegalSurname>
    <Gender>Male</Gender>
    <GenderID>0</GenderID>
    <DOB>1986-01-17T00:00:00</DOB>
    <BirthCertificateSeen>F</BirthCertificateSeen>
    <AttendanceMode>All Day</AttendanceMode>
    <AttendanceModeID>-1</AttendanceModeID>
    <FormerUPN />
    <UniqueLearnerNumber />
    <YearTaughtIn />
    <YearTaughtInID />
    <EmergencyConsent>F</EmergencyConsent>
    <NHSNumber />
    <BloodGroup />
    <EthnicDataSource>Provided by the parent</EthnicDataSource>
    <EthnicDataSourceID>2019</EthnicDataSourceID>
    <HomeLanguage>English</HomeLanguage>
    <HomeLanguageID>366</HomeLanguageID>
    <FirstLanguage>English</FirstLanguage>
    <FirstLanguageID>2027</FirstLanguageID>
    <EnglishAdditionalLanguage />
    <EnglishAdditionalLanguageID />
    <NationalIdentity />
    <NationalIdentityID />
    <AdmissionNumber>001511</AdmissionNumber>
    <UPN>U820432190122</UPN>
    <Religion>Christian*</Religion>
    <ReligionID>339</ReligionID>
    <RegGroup />
    <RegGroupID />
    <YearGroup />
    <YearGroupID />
    <House />
    <HouseID />
    <RollMode>Single Registration</RollMode>
    <RollModeID>2</RollModeID>
    <AdmissionDate>1997-09-03T00:00:00</AdmissionDate>
    <DateOfLeaving>2004-07-23T23:59:00</DateOfLeaving>
    <ParentalSalutation>Mr F and Mrs R Abbot</ParentalSalutation>
  </Student>
</StudentExtendeds>

Please note that the SIMS user invoking the call must have access to all of the data returned by the call for it to be successful.

It is then just a case of parsing the XML to get the name information.  (We already have the group information).  Partners may consider adding the Admission Number to the name to enable correct identification in areas of significant duplication of names.

Recording an attendance mark

We now have:

  •               An attendance date
  •               An attendance session   (AM/PM)
  •               A validatable mark
  •               A student ID (or a set thereof)
DateTime lDate = DateTime.Now; // Attendance Date
string lSession = "AM";    // AM/PM
string lCode = "X";       // Mark to save
int lStudentId = 2447;                                     // 
string saveIt = "<SessionAttendances>";
saveIt += formatAttendanceMark(lDate, lSession, lStudentId, lCode);
// Add the end tag
saveIt += "</SessionAttendances>";
// Fire of the new tpbo to save the marks.
SIMS.Processes.TPAttendanceWrite tpaw = new SIMS.Processes.TPAttendanceWrite();
tpaw.WriteSessionAttendances(saveIt);

Ironically the hardest part is formatting the Attendance Mark XML for the save and hence the function below:
 

/// <summary>
/// The new third party business object to save session attendance marks requires
/// the creation of a string of formatted XML.
/// The outer Tag is 
/// <SessionAttendances>
/// </SessionAttendances>
/// and there should be one or more instances of <SessionAttendance> </SessionAttendance>
/// formatted as below.  
/// </summary>
/// <param name="date"></param>
/// <param name="session"></param>
/// <param name="person_id"></param>
/// <param name="mark"></param>
/// <returns></returns>
private string formatAttendanceMark(DateTime date, string session, int person_id, string mark)
{
    StringBuilder element = new StringBuilder();
    element.Append("<SessionAttendance><PersonID>");
    element.Append(person_id);
    element.Append("</PersonID><AttendanceDate>");
    element.Append(date.Year.ToString());
    element.Append("-");
    string month = date.Month.ToString();
    element.Append(month.Length == 1 ? "0" + month : month);
    element.Append("-");
    string day = date.Day.ToString();
    element.Append(day.Length == 1 ? "0" + day : day);
    element.Append("</AttendanceDate><SessionName>");
    element.Append(session);
    element.Append("</SessionName><AttendanceMark>");
    element.Append(mark);
    element.Append("<Comments>Added by Andys Demo App</Comments>");
    if (!string.IsNullOrEmpty(minsLate))
    {
        element.AppendFormat("<MinsLate>{0}</MinsLate>", minsLate);
    }
    element.Append("</AttendanceMark></SessionAttendance>");
    return element.ToString();
}

It was less than obvious when earlier versions failed because of dates formatted differently!

 

Handling Errors

// See of there were errors or not.
SIMS.Entities.ValidationErrors errors = tpaw.ValidationMessages;
// Create a displayable 
StringBuilder mess = new StringBuilder();
bool errorsExist = false;  // Marker for errors
foreach (SIMS.Entities.ValidationError err in errors)
{
   errorsExist = true;
   mess.Append(err.Message +"\r\n");
}
// Display the messages
if (errorsExist)
{
    MessageBox.Show(mess.ToString(), "Errors Exist");
}

It is easy to assume that all saves will succeed, however any errors can be identified using the above code.  

It is less easy to bubble the errors up to those responsible for entering the data if the data is synchronised when the user is ‘off line’. In this type of scheduled system, it becomes critical to ensure that the validation is as good as possible  to minimise problems.

Conclusion

It is relatively simple to record session attendance marks.  However, data extracted for later update may find that marks have been updated in SIMS.  There is also the concept of conflicting marks, these however typically should only be applicable to lesson attendance because the last write for a mark from a partner system should prevail.