using System;
using SmartInstitute;
using SmartInstitute.DataAccessLayer.Factories;
using Microsoft.Practices.EnterpriseLibrary.Security;
namespace SmartInstitute.Facade
{
/// <summary>
/// Business Facade which provides convenient interface to complex subsystems
/// </summary>
public class Facade
{
#region Constants
private const string COURSE_CACHE = "Cache.CourseCache";
private const string STUDENT_LIST_CACHE = "Cache.StudentListCache";
private const string STUDENT_DETAIL_CACHE = "Cache.StudentDetailsCache";
#endregion
#region Student Management
/// <summary>
/// Get all the students. Only stuent basic information is returned. In order to get
/// details, call the <see cref="GetStudentDetails"/> method.
/// </summary>
/// <remarks><seealso cref="GetStudentDetails"/></remarks>
/// <returns>Collection of student basic information</returns>
public StudentCollection GetAllStudents()
{
StudentCollection students = EntLibHelper.GetCachedObject( STUDENT_LIST_CACHE ) as StudentCollection;
if( null == students )
{
students = StudentRepository.Current.GetAll();
EntLibHelper.StoreInCache( STUDENT_LIST_CACHE, students );
}
return students;
}
/// <summary>
/// Returns the details of a student including all courses taken, assessment and accounts
/// </summary>
/// <remarks><see cref="GetStudentRegistration"/> is called to get the registered courses.</remarks>
/// <param name="studentID"></param>
/// <returns>Student object containing all child collections populated</returns>
public Student GetStudentDetail( int studentID )
{
try
{
// Get the basic student object without children
Student student = StudentRepository.Current.GetByID( studentID )[0];
// Load student with accounts and assesments, the courses will be loaded later on
StudentRepository.Current.DeepLoad( student, true, DataAccessLayer.DeepLoadType.IncludeChildren,
new Type [] { typeof( AssessmentCollection ), typeof( AccountCollection ) } );
// Get courses taken by student with full details
student.CourseTakenByStudentCollection = this.GetRegisteredCourses( studentID );
return student;
}
catch( Exception x )
{
if( EntLibHelper.Exception( "GetStudentDetail", x ) )
throw x;
else
return null;
}
}
public bool SaveStudent( Student student )
{
return StudentRepository.Current.Update( student );
}
public int SaveStudents( StudentCollection students )
{
return StudentRepository.Current.Update( students );
}
public bool DeleteStudent( int studentID )
{
Student student = StudentRepository.Current.GetByID( studentID )[0];
bool result = StudentRepository.Current.Delete( student );
return result;
}
public bool AddNewStudent( Student student )
{
return StudentRepository.Current.Insert( student );
}
/// <summary>
/// Add the specified course collection to student's registration.
/// </summary>
/// <param name="studentID"></param>
/// <param name="coursesTaken"></param>
/// <returns></returns>
public int RegisterCourses( int studentID, CourseTakenByStudentCollection coursesTaken )
{
foreach( CourseTakenByStudent courseTaken in coursesTaken )
courseTaken.StudentID = studentID;
return CourseTakenByStudentRepository.Current.Insert( coursesTaken );
}
/// <summary>
/// Loads the courses the student has taken along with all referenced objects
/// fully populated. The collection contains a decorated Course Taken By Student object
/// which exposes the Course and Section object
/// </summary>
/// <param name="studentID"></param>
/// <returns></returns>
public CourseTakenByStudentCollection GetRegisteredCourses( int studentID )
{
CourseTakenByStudentCollection coursesTaken = CourseTakenByStudentRepository.Current.GetByStudentID( studentID );
CourseTakenByStudentCollection newCollection = new CourseTakenByStudentCollection();
foreach( CourseTakenByStudent courseTaken in coursesTaken )
{
CourseTakenByStudent2 newCourseTaken = new CourseTakenByStudent2( courseTaken );
newCourseTaken.Course = this.GetCourseDetail( newCourseTaken.CourseID );
newCourseTaken.Section = this.GetCourseSectionDetail( newCourseTaken.SectionID );
newCollection.Add( newCourseTaken );
}
return newCollection;
}
/// <summary>
/// Update the registration of the student and recalculate assessment
/// </summary>
/// <param name="studentID"></param>
/// <param name="coursesTaken"></param>
/// <returns></returns>
public bool SaveRegistration( int studentID, CourseTakenByStudentCollection coursesTaken )
{
CourseTakenByStudentRepository.Current.Save( coursesTaken );
Assessment newAssessment = this.CalculateAssessment( studentID );
return this.SaveAssessment( studentID, newAssessment );
}
/// <summary>
/// Saves changes made in the specified student object and all child objects
/// like accounts, assessment, courses taken etc.
/// </summary>
/// <param name="student"></param>
/// <returns></returns>
public bool SyncStudent( Student student )
{
if( this.SaveStudent( student ) )
{
AccountRepository.Current.Save( student.AccountCollection );
this.SaveRegistration( student.ID, student.CourseTakenByStudentCollection );
return true;
}
else
{
return false;
}
}
#endregion
#region Course Management
public CourseCollection GetAllCourses()
{
return CourseRepository.Current.GetAll();
}
public CourseCollection GetAllCoursesAndSections()
{
/// See if the course is cached. If cached, return cached data
CourseCollection courses = EntLibHelper.GetCachedObject( COURSE_CACHE ) as CourseCollection;
// If not cache, load it and return the cached data
if( null == courses )
{
courses = CourseRepository.Current.GetAll();
CourseRepository.Current.DeepLoad( courses, true, DataAccessLayer.DeepLoadType.IncludeChildren,
new Type [] { typeof( CourseSectionCollection ), typeof( SectionRoutineCollection ) } );
EntLibHelper.StoreInCache( COURSE_CACHE, courses );
}
return courses;
}
public Course GetCourseDetail( int courseID )
{
Course course = CourseRepository.Current.GetByID( courseID )[0];
CourseRepository.Current.DeepLoad( course, true, DataAccessLayer.DeepLoadType.IncludeChildren,
new Type [] { typeof( CourseSectionCollection ), typeof( SectionRoutineCollection ) } );
return course;
}
public bool SaveCourse( Course Course )
{
return CourseRepository.Current.Update( Course );
}
public int SaveCourses( CourseCollection Courses )
{
return CourseRepository.Current.Update( Courses );
}
public bool DeleteCourse( int userID )
{
Course Course = CourseRepository.Current.GetByID( userID )[0];
return CourseRepository.Current.Delete( Course );
}
public int AddNewCourses( CourseCollection Courses )
{
return CourseRepository.Current.Insert( Courses );
}
#endregion
#region Section Management
public CourseSectionCollection GetAllCourseSections()
{
return CourseSectionRepository.Current.GetAll();
}
public CourseSection GetCourseSectionDetail( int sectionID )
{
CourseSection section = CourseSectionRepository.Current.GetByID( sectionID )[0];
CourseSectionRepository.Current.DeepLoad( section, true, DataAccessLayer.DeepLoadType.IncludeChildren,
new Type [] { typeof( SectionRoutineCollection ) } );
return section;
}
public bool SaveCourseSection( CourseSection CourseSection )
{
return CourseSectionRepository.Current.Update( CourseSection );
}
public int SaveCourseSections( CourseSectionCollection CourseSections )
{
return CourseSectionRepository.Current.Update( CourseSections );
}
public bool DeleteCourseSection( int userID )
{
CourseSection CourseSection = CourseSectionRepository.Current.GetByID( userID )[0];
bool result = CourseSectionRepository.Current.Delete( CourseSection );
return result;
}
public int AddNewCourseSections( CourseSectionCollection CourseSections )
{
return CourseSectionRepository.Current.Insert( CourseSections );
}
#endregion
#region Account Management
public AccountCollection GetAccountsOfStudent( int studentID )
{
return AccountRepository.Current.GetByStudentID( studentID );
}
public bool SaveAccount( Account account )
{
if( AccountRepository.Current.Update( account ) )
return this.RecalculateBalance( account.StudentID );
else
return false;
}
public int SaveAccounts( AccountCollection accounts )
{
int rows = AccountRepository.Current.Update( accounts );
if( rows > 0 )
this.RecalculateBalance( accounts[0].StudentID );
return rows;
}
public bool DeleteAccount( int accountID )
{
Account Account = AccountRepository.Current.GetByID( accountID )[0];
bool result = AccountRepository.Current.Delete( Account );
return result;
}
public bool AddNewAccount( Account account )
{
if( AccountRepository.Current.Insert( account ) )
return this.RecalculateBalance( account.StudentID );
else
return false;
}
public int AddNewAccounts( AccountCollection accounts )
{
int rows = AccountRepository.Current.Insert( accounts );
if( rows > 0 )
this.RecalculateBalance( accounts[0].StudentID );
return rows;
}
/// <summary>
/// Recalculates the balance of all account head. Balance = Debit - Credit
/// </summary>
/// <param name="studentID"></param>
/// <returns></returns>
public bool RecalculateBalance( int studentID )
{
AccountCollection accounts = this.GetAccountsOfStudent( studentID );
decimal balance = 0;
int expectedUpdates = 0;
foreach( Account account in accounts )
{
balance += account.DebitAmount;
balance -= account.CreditAmount;
account.Balance = balance;
if( account.IsDirty ) expectedUpdates ++;
}
return this.SaveAccounts( accounts ) == expectedUpdates;
}
#endregion
#region Assessment Management
public Assessment CalculateAssessment( int studentID )
{
Assessment newAssessment = new Assessment();
newAssessment.ActivityFee = 1000;
newAssessment.AdmissionFee = 10000;
newAssessment.ComputerLabFee = 1000;
newAssessment.Currency = 1;
newAssessment.DevelopmentFee = 8000;
newAssessment.Discount = 0;
newAssessment.DiscountInPercent = 0;
newAssessment.ExamPermitNumber = "A" + studentID;
newAssessment.IDCardFee = 100;
newAssessment.IsAdmissionFeePaid = true;
newAssessment.IsAnnualFeePaid = true;
newAssessment.LibraryFee = 500;
newAssessment.MedicalFee = 0;
newAssessment.MiscFee = 0;
newAssessment.OtherDiscount = 100;
newAssessment.OtherDiscountDesc = "Promitional";
newAssessment.OtherFee1 = 0;
newAssessment.OtherFee1Desc = string.Empty;
newAssessment.OtherFee2 = 0;
newAssessment.OtherFee2Desc = string.Empty;
newAssessment.PaymentType = 1;
newAssessment.RegistrationDate = DateTime.Now;
newAssessment.Scholarship = 0;
newAssessment.ScholarshipInPercent = 0;
newAssessment.ScienceLabFee = 0;
newAssessment.SemesterOrder = 1;
newAssessment.Serial = 1;
newAssessment.StudentID = studentID;
newAssessment.TuitionFee = CalculateTuitionFee( studentID );
newAssessment.ChangeStamp = DateTime.Now;
return newAssessment;
}
/// <summary>
/// Calculate the total tuition fee for the student. Tuition Fee = SUM( Credit * 3000 )
/// You should make the amount configurable
/// </summary>
/// <param name="studentID"></param>
/// <returns></returns>
public decimal CalculateTuitionFee( int studentID )
{
decimal tuitionFee = 0;
CourseTakenByStudentCollection coursesTaken = this.GetRegisteredCourses( studentID );
foreach( CourseTakenByStudent2 courseTaken in coursesTaken )
{
if( !courseTaken.Dropped )
tuitionFee += 3000 // Read this from config in real app
* courseTaken.Course.LecCredit;
}
return tuitionFee;
}
/// <summary>
/// Update/Create assessment for the student and also update the account head
/// </summary>
/// <param name="studentID"></param>
/// <param name="assessment"></param>
/// <returns></returns>
public bool SaveAssessment( int studentID, Assessment assessment )
{
assessment.StudentID = studentID;
this.ClearAssessment( studentID );
bool result = UpdateAssessmentInAccount( studentID, assessment );
// Insert the new one
result &= AssessmentRepository.Current.Insert( assessment );
return result;
}
public Assessment GetAssessment( int studentID )
{
AssessmentCollection asses = AssessmentRepository.Current.GetByStudentID( studentID );
if( asses.Count > 0 )
return asses[0];
else
return null;
}
/// <summary>
/// Accounts contains one row which has a debit value and contains the assessed total amount
/// </summary>
/// <param name="studentID"></param>
/// <param name="ass"></param>
/// <returns></returns>
public bool UpdateAssessmentInAccount( int studentID, Assessment ass )
{
AccountCollection accounts = this.GetAccountsOfStudent( studentID );
// Check if there is already an account row which contains the assessed debit amount
foreach( Account account in accounts )
{
if( account.Type == (int)AccountTypeEnum.Assessment )
{
account.DebitAmount = ass.NetTotal;
return this.SaveAccount( account );
}
}
// None found, add a new account head
Account assAccount = new Account(0, studentID, "Total Assessment", DateTime.Now,
ass.NetTotal, 0, 0, DateTime.Now, (int)AccountTypeEnum.Assessment, string.Empty, string.Empty, string.Empty );
return this.AddNewAccount( assAccount );
}
/// <summary>
/// Clear all assessments for this student. Note: there should be only one per student
/// </summary>
/// <param name="studentID"></param>
/// <returns></returns>
public bool ClearAssessment( int studentID )
{
bool result = true;
// Clear previous assessment
AssessmentCollection oldAssessments = AssessmentRepository.Current.GetByStudentID( studentID );
foreach( Assessment oldAssessment in oldAssessments )
result &= AssessmentRepository.Current.Delete( oldAssessment );
return result;
}
#endregion
#region Security
public string Login( string userName, string passwordHash )
{
string key;
if( (key = EntLibHelper.Authenticate( userName, passwordHash )) != null )
{
if( EntLibHelper.IsAuthorized( userName, Constants.Authorization.CAN_LOGIN ) )
return key;
else
return null;
}
else
{
return null;
}
}
public bool Login( string token )
{
return EntLibHelper.Authenticate( token );
}
public void Logout( string token )
{
EntLibHelper.CleanSecurityToken( token );
}
public bool IsInRole( string userName, string role )
{
return EntLibHelper.IsInRole( userName, role );
}
public bool IsAuthorized( string userName, string task )
{
return EntLibHelper.IsAuthorized( userName, task );
}
#endregion
}
}