diff --git a/db/StoredFunctions.sql b/db/StoredFunctions.sql
index d85c6821a9c1ff7ca443983c6d7fb4fd87211b7e..3340ea0cc940690ab4327fb93809f1a4a0bc08b7 100644
--- a/db/StoredFunctions.sql
+++ b/db/StoredFunctions.sql
@@ -18,6 +18,18 @@ DROP FUNCTION IF EXISTS OrderModuleTypesForSession//
 
 DROP FUNCTION IF EXISTS CreateStudyGroup//
 
+DROP FUNCTION IF EXISTS GetAccCountByCode//
+DROP FUNCTION IF EXISTS GetAccCountByMail//
+DROP FUNCTION IF EXISTS GetAccCountByLogin//
+
+DROP FUNCTION IF EXISTS ChangePassword//
+DROP FUNCTION IF EXISTS ChangeLogin//
+DROP FUNCTION IF EXISTS ChangeMail//
+
+DROP FUNCTION IF EXISTS GetRateForDisc//
+
+drop function if exists InternalIsTeacherBound//
+
 
 # -------------------------------------------------------------------------------------------
 # Label: abbreviations
@@ -34,91 +46,86 @@ DROP FUNCTION IF EXISTS CreateStudyGroup//
 # actually check for first scoring, in this case you cannot yet edit discipline
 # "SetRate" stored procedure can change isLocked flag
 DROP FUNCTION IF EXISTS InternalIsMapLocked//
-CREATE FUNCTION `InternalIsMapLocked`
-    (`pDisciplineID` INT) RETURNS BOOLEAN
+CREATE FUNCTION `InternalIsMapLocked` (
+        `pDisciplineID` INT
+    ) RETURNS BOOLEAN
     NO SQL
 BEGIN
-    RETURN EXISTS(
-        SELECT * FROM `disciplines`
-        WHERE disciplines.ID = pDisciplineID AND disciplines.isLocked = 1
-    );
+    DECLARE vChecker BOOLEAN DEFAULT FALSE;
+
+    SELECT disciplines.isLocked INTO vChecker
+        FROM `disciplines`
+        WHERE disciplines.ID = pDisciplineID
+        LIMIT 1;
+
+    RETURN vChecker;
 END //
 
 
 # check, that student really take this course
 DROP FUNCTION IF EXISTS InternalIsStudentAttached//
-CREATE FUNCTION `InternalIsStudentAttached`
-    (`pStudentID` INT, `pDisciplineID` INT) RETURNS BOOLEAN
+CREATE FUNCTION `InternalIsStudentAttached` (
+        `pStudentID` INT,
+        `pDisciplineID` INT,
+        `pSemesterID` INT
+    ) RETURNS BOOLEAN
     NO SQL
 BEGIN
-    RETURN EXISTS(
-        SELECT * FROM `view_disciplines_students`
-        WHERE view_disciplines_students.SemesterID = @CurrentSemesterID AND
+    DECLARE vAttachType enum('attach','detach') DEFAULT NULL;
+
+    SELECT view_disciplines_students.AttachType INTO vAttachType
+        FROM `view_disciplines_students`
+        WHERE view_disciplines_students.SemesterID = pSemesterID AND
               view_disciplines_students.StudentID = pStudentID AND
-              view_disciplines_students.DisciplineID = pDisciplineID AND
-              (view_disciplines_students.AttachType IS NULL OR
-                  view_disciplines_students.AttachType = 'attach')
-        );
+              view_disciplines_students.DisciplineID = pDisciplineID
+        LIMIT 1;
+
+    RETURN ( NOT vAttachType  <=> 'detach' );
 END //
 
 
+
 # check, that teacher teach this course
-drop function if exists InternalIsTeacherBounded//
-CREATE FUNCTION `InternalIsTeacherBounded`
-    (   `pTeacherID` INT, `pDisciplineID` INT) RETURNS BOOLEAN
+DROP FUNCTION IF EXISTS InternalIsTeacherBound//
+CREATE FUNCTION InternalIsTeacherBound (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
+    ) RETURNS BOOLEAN
     NO SQL
 BEGIN
-    RETURN EXISTS (SELECT * FROM `disciplines_teachers`
-                   WHERE disciplines_teachers.TeacherID = pTeacherID AND
-                         disciplines_teachers.DisciplineID = pDisciplineID);
+    RETURN EXISTS (
+        SELECT * FROM `disciplines_teachers`
+            WHERE   disciplines_teachers.TeacherID = pTeacherID AND
+                    disciplines_teachers.DisciplineID = pDisciplineID
+            LIMIT 1
+    );
 END //
 
 
 DROP FUNCTION IF EXISTS InternalIsTeacherAuthor//
-CREATE FUNCTION `InternalIsTeacherAuthor`
-    (   `pTeacherID` INT, `pDisciplineID` INT) RETURNS BOOLEAN
-    NO SQL
-BEGIN
-    RETURN EXISTS (SELECT * FROM `disciplines`
-                        WHERE disciplines.ID = pDisciplineID AND disciplines.AuthorID = pTeacherID);
-END //
-
-
-DROP FUNCTION IF EXISTS GetRateForDisc//
-CREATE FUNCTION `GetRateForDisc`
-    (   `pStudentID` INT, `pDisciplineID` INT) RETURNS int(11)
+CREATE FUNCTION `InternalIsTeacherAuthor` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
+    ) RETURNS BOOLEAN
     NO SQL
 BEGIN
-    DECLARE vRate INT DEFAULT -1;
+    DECLARE vAuthorID INT DEFAULT -1;
 
-    SELECT SUM(rating_table.Rate)
-        INTO vRate
-        FROM `rating_table`
-        INNER JOIN `submodules` ON  rating_table.SubmoduleID = submodules.ID
-        INNER JOIN `modules`    ON  submodules.ModuleID = modules.ID AND
-                                    modules.DisciplineID = pDisciplineID
-        WHERE   rating_table.StudentID = pStudentID AND
-            (   modules.Type != 'exam' OR
-                submodules.ID =
-                    (   SELECT submodules.ID
-                        FROM `submodules`
-                        INNER JOIN `rating_table` ON rating_table.SubModuleID = submodules.ID
-                        WHERE   submodules.ModuleID = modules.ID AND
-                                rating_table.StudentID = pStudentID
-                        ORDER BY submodules.OrderNum DESC
-                        LIMIT 1
-                    )
-            )
+    SELECT disciplines.AuthorID INTO vAuthorID
+        FROM `disciplines`
+        WHERE disciplines.ID = pDisciplineID
         LIMIT 1;
 
-    RETURN  vRate;
+    RETURN ( vAuthorID = pTeacherID );
 END //
 
 
+
 DROP FUNCTION IF EXISTS SetExamPeriodOption//
-CREATE FUNCTION `SetExamPeriodOption`
-    (   `pStudentID` INT, `pSubmoduleID` INT,
-        `pType` VARCHAR(30) CHARSET utf8 # enum('absence','pass')
+CREATE FUNCTION `SetExamPeriodOption` (
+        `pStudentID` INT,
+        `pSubmoduleID` INT,
+        `pType` enum('absence','pass')
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -127,29 +134,34 @@ BEGIN
     INSERT INTO `exam_period_options`
         (StudentID, SubmoduleID, Type) VALUES(pStudentID, pSubmoduleID, pType)
         ON DUPLICATE KEY UPDATE
-        exam_period_options.Type = pType;
+            exam_period_options.Type = pType;
 
     RETURN  0;
 END //
 
 
-# check, if any module is created
+# check, regular + exam rate == 100
 DROP FUNCTION IF EXISTS InternalIsMapCreated//
-CREATE FUNCTION `InternalIsMapCreated`
-    (   `pDisciplineID` INT) RETURNS int(11)
+CREATE FUNCTION `InternalIsMapCreated` (
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
-    RETURN EXISTS (
-        SELECT * FROM `view_disciplines_results`
-        WHERE view_disciplines_results.DisciplineID = pDisciplineID AND
-              view_disciplines_results.DisciplineRateMax = 100
-    );
+    DECLARE vMaxRate INT DEFAULT -1;
+
+    SELECT view_disciplines_results.DisciplineRateMax INTO vMaxRate
+        FROM `view_disciplines_results`
+        WHERE view_disciplines_results.DisciplineID = pDisciplineID
+        LIMIT 1;
+
+    RETURN ( vMaxRate = 100 );
 END //
 
 # ordering helper
 DROP FUNCTION IF EXISTS InternalOrderModuleTypesForSession//
-CREATE FUNCTION `InternalOrderModuleTypesForSession`
-    (`pModuleType` INT ) RETURNS INT(3)
+CREATE FUNCTION `InternalOrderModuleTypesForSession` (
+        `pModuleType` INT
+    ) RETURNS INT(3)
     NO SQL
 BEGIN
     DECLARE vRes INT DEFAULT 0;
@@ -158,7 +170,7 @@ BEGIN
         WHEN 4 THEN SET vRes = 1; # extra
         WHEN 2 THEN SET vRes = 2; # exam
         WHEN 3 THEN SET vRes = 3; # bonus
-    ELSE SET vRes = 4;
+        ELSE SET vRes = 4;
     END CASE;
 
     RETURN vRes;
@@ -175,28 +187,32 @@ END //
 # set values of record with key \pKey,
 # if doesn't exist, then create.
 DROP FUNCTION IF EXISTS SetSettings//
-CREATE FUNCTION `SetSettings`
-    (`pKey` VARCHAR(50) CHARSET utf8, `pVal` INT, `pValS` VARCHAR(300) CHARSET utf8
+CREATE FUNCTION `SetSettings` (
+        `pKey` VARCHAR(50) CHARSET utf8,
+        `pVal` INT,
+        `pValS` VARCHAR(300) CHARSET utf8
     ) RETURNS int(11)
     NO SQL
 BEGIN
     INSERT INTO `general_settings`
-        (Val, ValS, Name) VALUES(pVal, pValS, pKey)
+        (Val, ValS, Name) VALUES (pVal, pValS, pKey)
         ON DUPLICATE KEY UPDATE
             general_settings.Val = pVal,
             general_settings.ValS = pValS;
-        RETURN 0;
+    RETURN 0;
 END//
 
 
 
 DROP FUNCTION IF EXISTS SetBitmaskByPagename//
-CREATE FUNCTION `SetBitmaskByPagename`
-    (`pPagename` TEXT CHARSET utf8, `pMask` INT) RETURNS int(11)
+CREATE FUNCTION `SetBitmaskByPagename` (
+        `pPagename` TEXT CHARSET utf8,
+        `pMask` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     INSERT INTO `page_access`
-        (Pagename, Bitmask) VALUES(pPagename, pMask)
+        (Pagename, Bitmask) VALUES (pPagename, pMask)
         ON DUPLICATE KEY UPDATE
             page_access.Bitmask = pMask;
     RETURN 0;
@@ -205,13 +221,19 @@ END //
 
 
 DROP FUNCTION IF EXISTS GetBitmaskByPagename//
-CREATE FUNCTION `GetBitmaskByPagename` (`pPagename` TEXT CHARSET utf8) RETURNS int(11)
+CREATE FUNCTION `GetBitmaskByPagename` (
+        `pPagename` TEXT CHARSET utf8
+    ) RETURNS int(11)
     NO SQL
 BEGIN
-    RETURN (SELECT page_access.Bitmask
-                FROM `page_access`
-                WHERE page_access.Pagename = pPagename
-                LIMIT 1);
+    DECLARE vBitmask INT DEFAULT 0;
+
+    SELECT page_access.Bitmask INTO vBitmask
+        FROM `page_access`
+        WHERE page_access.Pagename = pPagename
+        LIMIT 1;
+
+    RETURN vBitmask;
 END //
 
 
@@ -221,33 +243,24 @@ END //
 # Label: semesters
 # -------------------------------------------------------------------------------------------
 
-# set current(for user) semester, life time - db session
-DROP FUNCTION IF EXISTS SetSemesterID//
-CREATE FUNCTION `SetSemesterID` (`pSemesterID` INT) RETURNS int(11)
-    NO SQL
-BEGIN
-    SET @CurrentSemesterID := pSemesterID;
-    RETURN 0;
-END //
-
 
 
 # -------------------------------------------------------------------------------------------
 # Label: faculties
 # -------------------------------------------------------------------------------------------
 
+# TODO: return faculty id
 DROP FUNCTION IF EXISTS CreateFaculty //
-CREATE FUNCTION CreateFaculty
-    (   `pFacultyName` VARCHAR(100) CHARSET utf8,
-        `pFacultyAbbr` VARCHAR(20) CHARSET utf8
-    ) RETURNS INT(11)
+CREATE FUNCTION CreateFaculty (
+        `pFacultyName` TEXT CHARSET utf8,
+        `pFacultyAbbr` TEXT CHARSET utf8
+    ) RETURNS INT(11) # 0 - success
     NO SQL
 BEGIN
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
     INSERT INTO faculties
-    (Name, Abbr)
-    VALUES(pFacultyName, pFacultyAbbr);
+        (Name, Abbr) VALUES(pFacultyName, pFacultyAbbr);
     RETURN 0;
 END //
 
@@ -255,40 +268,66 @@ END //
 # Label: departments
 # -------------------------------------------------------------------------------------------
 
+# create department or return existing
 DROP FUNCTION IF EXISTS CreateDepartment //
-CREATE FUNCTION CreateDepartment
-    (   `pName` VARCHAR(200) CHARSET utf8,
+CREATE FUNCTION CreateDepartment (
+        `pName` VARCHAR(200) CHARSET utf8,
         `pFacultyID` INT(11)
-    ) RETURNS INT(11)
-NO SQL
-    BEGIN
-        DECLARE vChecker INT DEFAULT -1;
-        DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+    ) RETURNS INT(11) # department id or -1 if failed
+    NO SQL
+BEGIN
+    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+
+    INSERT INTO departments
+        (Name, FacultyID) VALUES (pName, pFacultyID)
+        ON DUPLICATE KEY UPDATE
+            departments.ID = LAST_INSERT_ID(departments.ID);
+
+    RETURN LAST_INSERT_ID();
+
+END //
+
+# -------------------------------------------------------------------------------------------
+# Label: specializations
+# -------------------------------------------------------------------------------------------
 
-        SELECT faculties.ID INTO vChecker
-        FROM `faculties`
-        WHERE faculties.ID = pFacultyID
-        LIMIT 1;
 
-        IF vChecker > 0 THEN
-            INSERT INTO departments
-            (Name, FacultyID)
-            VALUES(pName, pFacultyID);
-            RETURN 0;
-        END IF;
-        RETURN -1;
-    END //
 
 # -------------------------------------------------------------------------------------------
-# Label: study groups
+# Label: grades
 # -------------------------------------------------------------------------------------------
 
+DROP FUNCTION IF EXISTS CreateGrade//
+CREATE FUNCTION `CreateGrade` (
+    `pGradeNum` INT,
+    `pDegree` enum('bachelor', 'master', 'specialist')
+) RETURNS int(11) # groupID or -1 if failed
+    NO SQL
+BEGIN
+    DECLARE vGradeID INT DEFAULT -1;
+    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+
+    INSERT INTO `grades`
+    (Num, Degree) VALUES (pGradeNum, pDegree)
+    ON DUPLICATE KEY UPDATE
+        grades.ID = LAST_INSERT_ID(grades.ID);
+
+    RETURN LAST_INSERT_ID();
+END //
+
+# -------------------------------------------------------------------------------------------
+# Label: groups
+# -------------------------------------------------------------------------------------------
+
+
 # negative int, if already exists
 DROP FUNCTION IF EXISTS CreateGroup//
-CREATE FUNCTION `CreateGroup`
-    (   `pGradeID` INT, `pGroupNum` INT,
-        `pSpecializationID` INT, `pGroupName` VARCHAR(50) CHARSET utf8
-    )   RETURNS int(11)
+CREATE FUNCTION `CreateGroup` (
+    `pGradeID` INT,
+    `pGroupNum` INT,
+    `pSpecializationID` INT,
+    `pGroupName` VARCHAR(50) CHARSET utf8
+) RETURNS int(11) # group id
     NO SQL
 BEGIN
     # check GradeID, SpecID constraints and (GradeID, GroupNum, SpecID) - unique
@@ -297,69 +336,95 @@ BEGIN
     # create discipline
     INSERT INTO `study_groups`
         (GradeID, GroupNum, SpecializationID, Name)
-        VALUES (pGradeID, pGroupNum, pSpecializationID, pGroupName);
-    RETURN 0;
+        VALUES (pGradeID, pGroupNum, pSpecializationID, pGroupName)
+        ON DUPLICATE KEY UPDATE
+            study_groups.ID = LAST_INSERT_ID(study_groups.ID);
+    RETURN LAST_INSERT_ID();
 END //
 
 
+
+
+DROP FUNCTION IF EXISTS GetGroup//
+CREATE FUNCTION `GetGroup` (
+        `pGradeID` INT,
+        `pGroupNum` INT,
+        `pFacultyID` INT
+    ) RETURNS int(11) # groupID or -1 if failed
+    NO SQL
+BEGIN
+    DECLARE vGroupID INT DEFAULT -1;
+
+    SELECT study_groups.ID INTO vGroupID
+        FROM `study_groups`
+        INNER JOIN `specializations` ON specializations.ID = study_groups.SpecializationID
+        WHERE   study_groups.GradeID = pGradeID AND
+                study_groups.GroupNum = pGroupNum AND
+                specializations.FacultyID = pFacultyID
+        LIMIT 1;
+
+    RETURN vGroupID;
+END //
+
+
+
+
 # -------------------------------------------------------------------------------------------
 # Label: subjects
 # -------------------------------------------------------------------------------------------
 
 DROP FUNCTION IF EXISTS CreateSubject//
-CREATE FUNCTION `CreateSubject`
-    (   `pFacultyID` INT,
-        `pSubjectName` VARCHAR(200) CHARSET utf8,
+CREATE FUNCTION `CreateSubject` (
+        `pFacultyID` INT,
+        `pSubjectName` TEXT CHARSET utf8,
         `pSubjectAbbr` VARCHAR(20) CHARSET utf8
     )   RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vSubjectID INT DEFAULT -1;
 
-    # find same subject
-    SELECT subjects.ID INTO vSubjectID
-        FROM `subjects`
-        WHERE subjects.Name = pSubjectName
-        LIMIT 1;
-    IF vSubjectID <= 0 THEN
-        # create new subject
-        INSERT INTO `subjects`
-            (Name, Abbr) VALUES(pSubjectName, pSubjectAbbr);
-        SET vSubjectID = LAST_INSERT_ID();
-    END IF;
+    # create/get subject (subject name is unique key)
+    INSERT INTO `subjects`
+        (Name, Abbr) VALUES (pSubjectName, pSubjectAbbr)
+        ON DUPLICATE KEY UPDATE
+            subjects.ID = LAST_INSERT_ID(subjects.ID);
+    SET vSubjectID = LAST_INSERT_ID();
 
     BEGIN # handler block
         DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+
         # try to attach subject to faculty
         INSERT INTO `subjects_faculties`
-            (SubjectID, FacultyID)
-            VALUES (vSubjectID, pFacultyID)
+            (SubjectID, FacultyID) VALUES (vSubjectID, pFacultyID)
             ON DUPLICATE KEY UPDATE # just stub
-                subjects_faculties.FacultyID = subjects_faculties.FacultyID;
+                subjects_faculties.ID = LAST_INSERT_ID(subjects_faculties.ID);
     END;
+
     RETURN 0;
 END //
 
 
 DROP FUNCTION IF EXISTS DeleteSubject //
-CREATE FUNCTION DeleteSubject
-    (`pSubjectID` INT) RETURNS TEXT
+CREATE FUNCTION DeleteSubject (
+        `pSubjectID` INT
+    ) RETURNS INT(11) # 0 - success
     NO SQL
 BEGIN
-    DECLARE vChecker INT DEFAULT -1;
+    DECLARE vChecker BOOLEAN DEFAULT FALSE;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-    SELECT disciplines.ID INTO vChecker
-        FROM `disciplines`
+    SET vChecker = EXISTS(
+        SELECT * FROM `disciplines`
         WHERE disciplines.SubjectID = pSubjectID
-        LIMIT 1;
-    IF vChecker > 0 THEN
+        LIMIT 1
+    );
+    IF vChecker THEN
         RETURN -1; # Удаляемый предмет используется в disciplines.
     END IF;
 
     DELETE FROM `subjects_faculties`
         WHERE subjects_faculties.SubjectID = pSubjectID;
-        DELETE FROM `subjects`
+    DELETE FROM `subjects`
         WHERE subjects.ID = pSubjectID
         LIMIT 1;
 
@@ -371,40 +436,40 @@ END //
 # Label: accounts
 # -------------------------------------------------------------------------------------------
 
-# TODO: rename
-DROP FUNCTION IF EXISTS GetAccCountByCode//
-CREATE FUNCTION `GetAccCountByCode` (`pCode` VARCHAR(40) CHARSET utf8) RETURNS int(11)
-    NO SQL
-BEGIN
-    RETURN EXISTS(SELECT * FROM `accounts` WHERE accounts.ActivationCode = pCode);
-END //
 
 
-DROP FUNCTION IF EXISTS GetAccCountByMail //
-CREATE FUNCTION `GetAccCountByMail` (`pEMail` VARCHAR(50) CHARSET utf8) RETURNS int(11)
-    NO SQL
-BEGIN
-    RETURN EXISTS(SELECT * FROM `accounts` WHERE accounts.EMail = pEMail);
-END //
 
-
-DROP FUNCTION IF EXISTS GetAccCountByLogin//
-CREATE FUNCTION `GetAccCountByLogin` (`pLogin` VARCHAR(50) CHARSET utf8) RETURNS int(11)
+DROP FUNCTION IF EXISTS CheckAccountExistence//
+CREATE FUNCTION `CheckAccountExistence` (
+        `pData` TEXT CHARSET utf8,
+        `pType` enum('login','email', 'code')
+    ) RETURNS BOOLEAN # TRUE - exist, FALSE - doesn't
     NO SQL
 BEGIN
-    RETURN EXISTS(SELECT * FROM `accounts` WHERE accounts.Login = pLogin);
-END //
+    DECLARE vRes BOOLEAN DEFAULT FALSE;
 
+    SET vRes = EXISTS(
+        SELECT * FROM `accounts`
+            WHERE CASE pType
+                WHEN 'login' THEN pData = accounts.Login
+                WHEN 'email' THEN pData = accounts.EMail
+                WHEN 'code' THEN pData = accounts.ActivationCode
+                ELSE FALSE
+            END
+        LIMIT 1
+    );
 
+    RETURN vRes;
+END //
 
 
 DROP FUNCTION IF EXISTS ActivateAccount//
-CREATE FUNCTION `ActivateAccount`
-    (   `pCode` VARCHAR(40) CHARSET utf8,
+CREATE FUNCTION `ActivateAccount` (
+        `pCode` VARCHAR(40) CHARSET utf8,
         `pLogin` VARCHAR(50) CHARSET utf8,
         `pEMail` VARCHAR(50) CHARSET utf8,
         `pPassword` VARCHAR(255) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     # check for matching with existing accounts (note: Login & E-Mail are unique)
@@ -417,85 +482,61 @@ BEGIN
             accounts.EMail = pEMail,
             accounts.ActivationCode = NULL
         WHERE accounts.ActivationCode = pCode AND
-              (@vAccountID := accounts.ID) > 0 # save accountID
+              ( @vAccountID := accounts.ID ) # save accountID
         LIMIT 1;
 
-    IF (ROW_COUNT() = 0) THEN
+    IF ( ROW_COUNT() = 0 ) THEN
         RETURN -2; # account with this Code not found
+    ELSE
+        RETURN @vAccountID;
     END IF;
-    RETURN @vAccountID;
 END //
 
 
-
-DROP FUNCTION IF EXISTS ChangePassword//
-CREATE FUNCTION `ChangePassword`
-    (   `pUserID` INT, `pPassword` VARCHAR(255) CHARSET utf8
-    )   RETURNS int(11)
+DROP FUNCTION IF EXISTS ChangeAccountData//
+CREATE FUNCTION `ChangeAccountData` (
+        `pUserID` INT,
+        `pData` TEXT CHARSET utf8,
+        `pType` enum('login', 'email', 'password')
+    ) RETURNS int(11) # 0 - success, <0 - failed
     NO SQL
 BEGIN
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-    # set new password
-    UPDATE `accounts`
-        SET accounts.Password = pPassword
-        WHERE accounts.ID = pUserID
-        LIMIT 1;
-    RETURN ROW_COUNT()-1; # -1 if account doesn't exists, otherwise 0
-END //
-
-
-
-DROP FUNCTION IF EXISTS ChangeLogin//
-CREATE FUNCTION `ChangeLogin`
-    (   `pUserID` INT, `pLogin` VARCHAR(50) CHARSET utf8
-    )   RETURNS int(11)
-    NO SQL
-BEGIN
-    # check set login: login - unique
-    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
-
-    # set new login
-    UPDATE `accounts`
-        SET accounts.Login = pLogin
-        WHERE accounts.ID = pUserID
-        LIMIT 1;
-    RETURN ROW_COUNT()-1; # -1 if account doesn't exists, otherwise 0
-END //
-
-
-
-DROP FUNCTION IF EXISTS ChangeMail//
-CREATE FUNCTION `ChangeMail`
-    (`pUserID` INT, `pEMail` VARCHAR(50) CHARSET utf8
-    )   RETURNS int(11)
-    NO SQL
-BEGIN
-    # check set login: login - unique
-    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+    CASE pType
+        WHEN 'login' THEN
+            UPDATE `accounts`
+                SET accounts.Login = pData
+                WHERE accounts.ID = pUserID
+                LIMIT 1;
+        WHEN 'email' THEN
+            UPDATE `accounts`
+                SET accounts.EMail = pData
+                WHERE accounts.ID = pUserID
+                LIMIT 1;
+        WHEN 'password' THEN
+            UPDATE `accounts`
+                SET accounts.Password = pData
+                WHERE accounts.ID = pUserID
+                LIMIT 1;
+    END CASE;
 
-    # set new e-mail
-    UPDATE `accounts`
-        SET accounts.EMail = pEMail
-        WHERE accounts.ID = pUserID
-        LIMIT 1;
-    RETURN ROW_COUNT()-1; # -1 if account doesn't exists, otherwise 0
+    RETURN ROW_COUNT()-1;
 END //
 
 
 
 DROP FUNCTION IF EXISTS SignIn//
-CREATE FUNCTION `SignIn`
-    (   `pLoginOrMail` VARCHAR(255) CHARSET utf8,
+CREATE FUNCTION `SignIn` (
+        `pLoginOrMail` VARCHAR(255) CHARSET utf8,
         `pPassword`  VARCHAR(64) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11) # account id
     NO SQL
 BEGIN
     DECLARE vAccountID INT DEFAULT -1;
 
     #check account existence
-    SELECT accounts.ID
-        INTO vAccountID
+    SELECT accounts.ID INTO vAccountID
         FROM `accounts`
         WHERE   accounts.Password = pPassword AND
                 (accounts.Login = pLoginOrMail OR accounts.EMail = pLoginOrMail)
@@ -504,8 +545,8 @@ BEGIN
         RETURN -1;
     END IF;
 
-    # logging
-    INSERT INTO `logs_signin`
+    # TODO: extract method - log sign in
+    INSERT INTO `logs_signin` # logging
         (AccountID) VALUES (vAccountID);
     RETURN vAccountID;
 END //
@@ -518,14 +559,14 @@ END //
 # -------------------------------------------------------------------------------------------
 
 DROP FUNCTION IF EXISTS ChangeTeacherInfo//
-CREATE FUNCTION `ChangeTeacherInfo`
-    (   `pTeacherID` INT,
+CREATE FUNCTION `ChangeTeacherInfo` (
+        `pTeacherID` INT,
         `pLastName` VARCHAR(30) CHARSET utf8,
         `pFirstName` VARCHAR(30) CHARSET utf8,
         `pSecondName` VARCHAR(30) CHARSET utf8,
         `pJobPositionID` INT,
         `pDepartmentID` INT
-    ) RETURNS int(11)
+    ) RETURNS int(11) # -1 if teacher doesn't exists, otherwise 0
     NO SQL
 BEGIN
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
@@ -539,33 +580,34 @@ BEGIN
             teachers.DepartmentID = pDepartmentID
         WHERE teachers.ID = pTeacherID
         LIMIT 1;
-    RETURN ROW_COUNT()-1; # -1 if teacher doesn't exists, otherwise 0
+    RETURN ROW_COUNT()-1;
 END //
 
 
 
 DROP FUNCTION IF EXISTS CreateTeacher//
-CREATE FUNCTION `CreateTeacher`
-    (   `pLastName` VARCHAR(30) CHARSET utf8,
+CREATE FUNCTION `CreateTeacher` (
+        `pLastName` VARCHAR(30) CHARSET utf8,
         `pFirstName` VARCHAR(30) CHARSET utf8,
         `pSecondName` VARCHAR(30) CHARSET utf8,
         `pJobPositionID` INT,
         `pDepartmentID`  INT,
         `pActivationCode` VARCHAR(40) CHARSET utf8
-    ) RETURNS int(11)
+    ) RETURNS int(11) # 0 - success, <0 failed
     NO SQL
 BEGIN
     DECLARE vAccountID INT DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-# user role 2 - common teacher
-# add new account
+    # TODO: kill magic constants
+    # user role 2 - common teacher
+    # create account
     INSERT INTO `accounts`
         (Login , Password , EMail, UserRoleID, ActivationCode )
         VALUES  ( NULL, NULL, NULL, 2, pActivationCode);
     SET vAccountID = LAST_INSERT_ID();
 
-# add new teacher
+    # add new teacher
     INSERT INTO `teachers`
         (AccountID, LastName, FirstName, SecondName, JobPositionID, DepartmentID)
         VALUES  (vAccountID, pLastName, pFirstName, pSecondName, pJobPositionID, pDepartmentID);
@@ -573,50 +615,26 @@ BEGIN
 END //
 
 
-
 DROP FUNCTION IF EXISTS CreateTeacherByDepName//
-CREATE FUNCTION `CreateTeacherByDepName`
-    (   `pLastName` VARCHAR(30) CHARSET utf8,
+CREATE FUNCTION `CreateTeacherByDepName` (
+        `pLastName` VARCHAR(30) CHARSET utf8,
         `pFirstName` VARCHAR(30) CHARSET utf8,
         `pSecondName` VARCHAR(30) CHARSET utf8,
         `pDepartmentName` VARCHAR(200) CHARSET utf8,
         `pFacultyID` INT,
         `pActivationCode` VARCHAR(40) CHARSET utf8
-    )   RETURNS int(11)
+    )   RETURNS int(11) # 0 - success, < 0 - failed
     NO SQL
 BEGIN
-    DECLARE vAccountID, vChecker, vRoleID, vDepID INT DEFAULT -1;
+    DECLARE vAccountID, vRoleID, vDepID INT DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-    IF pDepartmentName = '' THEN
-        RETURN -1;
+    SET vDepID = CreateDepartment(pDepartmentName, pFacultyID);
+    IF vDepID < 0 THEN
+       RETURN -1;
     END IF;
 
-    # try to find a department with pDepartmentName
-    SELECT departments.ID
-        INTO vDepID
-        FROM `departments`
-        WHERE   (departments.Name = pDepartmentName AND departments.FacultyID = pFacultyID)
-        LIMIT 1;
-
-    IF vDepID <= 0 THEN
-        # pDepartmentName is not empty now
-        SET vChecker = CreateDepartment(pDepartmentName, pFacultyID);
-        IF vChecker < 0 THEN
-           RETURN -1;
-        END IF;
-        SET vDepID = LAST_INSERT_ID();
-    END IF;
-
-    INSERT INTO `accounts`
-        (Login , Password , EMail, UserRoleID, ActivationCode )
-        VALUES ( NULL, NULL, NULL, 2, pActivationCode);
-    SET vAccountID = LAST_INSERT_ID();
-
-    INSERT INTO `teachers`
-        (AccountID, LastName, FirstName, SecondName, JobPositionID, DepartmentID)
-        VALUES (vAccountID, pLastName, pFirstName, pSecondName, 12, vDepID);
-    RETURN 0;
+    RETURN CreateTeacher(pLastName, pFirstName, pSecondName, 12, vDepID, pActivationCode);
 END //
 
 
@@ -624,27 +642,25 @@ END //
 -- 0 - только чтение
 -- 1 - редактирование
 DROP FUNCTION IF EXISTS GetEditRightsForTeacher//
-CREATE FUNCTION `GetEditRightsForTeacher`   
-    (   `pTeacherID` INT,
+CREATE FUNCTION `GetEditRightsForTeacher` (
+        `pTeacherID` INT,
         `pDisciplineID` INT
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
-    DECLARE vUserRole, vDiscTeacherID INT DEFAULT -1;
-              
-    SELECT disciplines_teachers.ID INTO vDiscTeacherID
-        FROM `disciplines_teachers`
-        WHERE disciplines_teachers.DisciplineID = pDisciplineID AND
-              disciplines_teachers.TeacherID = pTeacherID;
+    DECLARE vUserRole INT DEFAULT -1;
+    DECLARE vIsBound BOOLEAN;
 
-    IF vDiscTeacherID > 0 THEN
+    SET vIsBound = InternalIsTeacherBound(pTeacherID, pDisciplineID);
+    IF vIsBound > 0 THEN
         RETURN 1;
     END IF;
 
     SELECT accounts.UserRoleID INTO vUserRole
         FROM `teachers`
         INNER JOIN `accounts` ON teachers.AccountID=accounts.ID
-        WHERE teachers.ID = pTeacherID;
+        WHERE teachers.ID = pTeacherID
+        LIMIT 1;
     IF vUserRole = 4 THEN # 4 - сотрудник деканата
         RETURN 0;
     END IF;
@@ -658,12 +674,17 @@ END //
 # Label: students
 # -------------------------------------------------------------------------------------------
 
+# TODO: magic constants (UserRoleID)
+# TODO: transaction
+# TODO: group id instead num and grade
 DROP FUNCTION IF EXISTS CreateStudent//
-CREATE FUNCTION `CreateStudent`
-    (   `pLastName` VARCHAR(30) CHARSET utf8,
+CREATE FUNCTION `CreateStudent` (
+        `pLastName` VARCHAR(30) CHARSET utf8,
         `pFirstName` VARCHAR(30) CHARSET utf8,
         `pSecondName` VARCHAR(30) CHARSET utf8,
-        `pGradeID` INT, `pGroupNum` INT, `pFacultyID` INT,
+        `pGradeID` INT,
+        `pGroupNum` INT,
+        `pFacultyID` INT,
         `pActivationCode` VARCHAR(40) CHARSET utf8
     )   RETURNS int(11)
     NO SQL
@@ -671,18 +692,13 @@ BEGIN
     DECLARE vAccountID, vGroupID, vStudentID, vSemesterID INT DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-    # find group
-    SELECT view_groups.GroupID INTO vGroupID
-        FROM `view_groups`
-        WHERE   view_groups.FacultyID = pFacultyID AND
-                view_groups.GradeID = pGradeID AND
-                view_groups.GroupNum = pGroupNum
-        LIMIT 1;
+    SET vGroupID = GetGroup(pGradeID, pGroupNum, pFacultyID);
     IF vGroupID <= 0 THEN
         RETURN -1;
     END IF;
 
     # create new account
+    # UserRoleID 1 = student
     INSERT INTO `accounts`
         (Login , Password , EMail, UserRoleID, ActivationCode )
         VALUES ( NULL, NULL, NULL, 1, pActivationCode);
@@ -692,31 +708,27 @@ BEGIN
     INSERT INTO `students`
         (AccountID, LastName, FirstName, SecondName)
         VALUES  (vAccountID, pLastName, pFirstName, pSecondName);
+    SET vStudentID = LAST_INSERT_ID();
 
-
+    # TODO: add param semester id
     SELECT general_settings.Val INTO vSemesterID
         FROM `general_settings`
         WHERE general_settings.Name = 'SemesterID'
         LIMIT 1;
 
-    # bind group in current semester
-    INSERT INTO `students_groups`
-        (StudentID, GroupID, SemesterID)
-        VALUES (LAST_INSERT_ID(), vGroupID, vSemesterID);
-
-    RETURN 0;
+    RETURN ControlStudentGroup(vStudentID, vGroupID, FALSE, vSemesterID);
 END //
 
 
 # unlike fn CreateStudent, this can create all missing records (group, grade, specialization)
 DROP FUNCTION IF EXISTS CreateStudentEx//
-CREATE FUNCTION `CreateStudentEx`
-    (   `pLastName` VARCHAR(30) CHARSET utf8,
+CREATE FUNCTION `CreateStudentEx` (
+        `pLastName` VARCHAR(30) CHARSET utf8,
         `pFirstName` VARCHAR(30) CHARSET utf8,
         `pSecondName` VARCHAR(30) CHARSET utf8,
         `pGradeNum` INT,
         `pGroupNum` INT,
-        `pDegree` VARCHAR(20) CHARSET utf8,
+        `pDegree` enum('bachelor', 'master', 'specialist'),
         `pSpecName` VARCHAR(50) CHARSET utf8,
         `pFacultyID` INT,
         `pActivationCode` VARCHAR(40) CHARSET utf8
@@ -726,53 +738,15 @@ BEGIN
     DECLARE vAccountID, vGradeID, vSpecID, vGroupID INT DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-    # try to find grade
-    SELECT grades.ID INTO vGradeID
-        FROM `grades`
-        WHERE grades.Num = pGradeNum AND grades.Degree = pDegree
-        LIMIT 1;
-    # such grade doesn't exist
-    IF vGradeID <= 0 THEN
-        # insert new grade with pGradeNum and pDegree
-        INSERT INTO `grades`
-            (Num, Degree) VALUES (pGradeNum, pDegree);
-        SET vGradeID = LAST_INSERT_ID();
-    END IF;
-
-    # try to find group
-    SELECT view_groups.GroupID INTO vGroupID
-        FROM `view_groups`
-        WHERE view_groups.FacultyID = pFacultyID AND
-            view_groups.GroupNum = pGroupNum AND
-            view_groups.GradeID = vGradeID
-        LIMIT 1;
-
-    # group not found
-    IF vGroupID <= 0 THEN
-        # try to find specialization
-        SELECT specializations.ID INTO vSpecID
-            FROM `specializations`
-            WHERE   (specializations.Name = pSpecName OR
-                        (pSpecName = '' AND specializations.Name IS NULL)) AND
-                    specializations.FacultyID = pFacultyID
-            LIMIT 1;
-
-        # specialization not found
-        IF vSpecID <= 0 THEN
-            # create new specialization
-            INSERT INTO `specializations`
-                (Name, Abbr, FacultyID)
-                VALUES  (pSpecName, NULL, pFacultyID);
-            SET vSpecID = LAST_INSERT_ID();
-        END IF;
-
-        # create new group
-        INSERT INTO `study_groups`
-            (GradeID, GroupNum, SpecializationID)
-            VALUES (vGradeID, pGroupNum, vSpecID);
-        SET vGroupID = LAST_INSERT_ID();
-    END IF;
+    # get specialization id
+    INSERT INTO `specializations`
+        (Name, Abbr, FacultyID) VALUES  (pSpecName, NULL, pFacultyID)
+        ON DUPLICATE KEY UPDATE
+            specializations.ID = LAST_INSERT_ID(specializations.ID);
+    SET vSpecID = LAST_INSERT_ID();
 
+    SET vGradeID = CreateGrade(pGradeNum, pDegree);
+    SET vGroupID = CreateGroup(vGradeID, pGroupNum, vSpecID, NULL);
     RETURN CreateStudent(pLastName, pFirstName, pSecondName, vGradeID, pGroupNum, pFacultyID, pActivationCode);
 END //
 
@@ -787,7 +761,8 @@ DROP FUNCTION IF EXISTS ControlStudentGroup//
 CREATE FUNCTION `ControlStudentGroup` (
         `pStudentID` INT,
         `pGroupID` INT,
-        `pState` BOOLEAN
+        `pState` BOOLEAN,
+        `pSemesterID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -800,13 +775,15 @@ BEGIN
             SET students_groups.IsStudyLeave = TRUE,
                 students_groups.Date = CURDATE()
             WHERE students_groups.StudentID = pStudentID AND
-                  students_groups.SemesterID = @CurrentSemesterID
+                  students_groups.SemesterID = pSemesterID
             LIMIT 1;
     # attach to new group
     ELSE
         INSERT INTO `students_groups`
             (StudentID, GroupID, SemesterID)
-            VALUES(pStudentID, pGroupID, @CurrentSemesterID);
+            VALUES(pStudentID, pGroupID, pSemesterID)
+            ON DUPLICATE KEY UPDATE
+                students_groups.GroupID = pGroupID;
     END IF;
     RETURN ROW_COUNT()-1;
 END //
@@ -818,6 +795,22 @@ END //
 
 
 
+DROP FUNCTION IF EXISTS GetDisciplineSemesterID//
+CREATE FUNCTION `GetDisciplineSemesterID` (
+    `pDisciplineID` INT
+) RETURNS int(11)
+    NO SQL
+BEGIN
+    DECLARE vSemesterID INT DEFAULT -1;
+
+    SELECT disciplines.SemesterID INTO vSemesterID
+        FROM `disciplines`
+        WHERE disciplines.ID = pDisciplineID
+        LIMIT 1;
+
+    RETURN vSemesterID;
+END //
+
 DROP FUNCTION IF EXISTS AddDiscipline//
 DROP FUNCTION IF EXISTS Discipline_Create//
 CREATE FUNCTION `Discipline_Create` (
@@ -839,17 +832,18 @@ BEGIN
 
     # create discipline
     INSERT INTO `disciplines`
-        (AuthorID, GradeID, SubjectID, ExamType, LectureCount, PracticeCount,LabCount, SemesterID, FacultyID, Subtype)
+        (AuthorID, GradeID, SubjectID, ExamType,
+        LectureCount, PracticeCount,LabCount,
+        SemesterID, FacultyID, Subtype)
         VALUES (
-            pTeacherID, pGradeID, pSubjectID, pExamType, pLectureCount,
-            pPracticeCount, pLabCount, pSemesterID, pFacultyID, pSubtype
+            pTeacherID, pGradeID, pSubjectID, pExamType,
+            pLectureCount, pPracticeCount, pLabCount,
+            pSemesterID, pFacultyID, pSubtype
         );
     SET vDisciplineID = LAST_INSERT_ID();
 
-    # bind teacher (author)
-    INSERT INTO `disciplines_teachers`
-        (DisciplineID,TeacherID)
-        VALUES (vDisciplineID, pTeacherID);
+
+    SET vChecker = BindTeacher(pTeacherID, pTeacherID, vDisciplineID);
 
     # add exam and extra modules
     IF pExamType = 'exam' THEN
@@ -863,14 +857,16 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeDisciplineSubject//
-CREATE FUNCTION `ChangeDisciplineSubject`
-    (`pTeacherID` INT, `pDisciplineID` INT, `pSubjectID` INT
+CREATE FUNCTION `ChangeDisciplineSubject` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pSubjectID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
-    IF NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
+    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
         InternalIsMapLocked(pDisciplineID)
     THEN
         RETURN -1;
@@ -885,15 +881,16 @@ END //
 
 
 
-
 DROP FUNCTION IF EXISTS GetMilestone//
-CREATE FUNCTION `GetMilestone`
-    (`pFacultyID` INT, `pSemesterID` INT
+CREATE FUNCTION `GetMilestone` (
+        `pFacultyID` INT,
+        `pSemesterID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vMilestone, vCounter INT DEFAULT 0;
 
+    # get most frequent milestone
     SELECT COUNT(*) AS 'cnt', disciplines.Milestone
         INTO vCounter, vMilestone
         FROM `disciplines`
@@ -909,8 +906,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeDisciplineGrade//
-CREATE FUNCTION `ChangeDisciplineGrade`
-    (`pTeacherID` INT, `pDisciplineID` INT, `pGradeID` INT
+CREATE FUNCTION `ChangeDisciplineGrade` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pGradeID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -948,13 +947,15 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeDisciplineControl//
-CREATE FUNCTION `ChangeDisciplineControl`
-    (   `pTeacherID` INT, `pDisciplineID` INT,
-        `pExamType` VARCHAR(30) CHARSET utf8
+CREATE FUNCTION `ChangeDisciplineControl` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pExamType` enum('exam', 'credit', 'grading_credit')
     )   RETURNS int(11)
     NO SQL
 BEGIN
-    DECLARE vOldExamType, vChecker, vExtraMax, vExtraID INT DEFAULT -1;
+    DECLARE vChecker, vExtraMax, vExtraID INT DEFAULT -1;
+    DECLARE vOldExamType enum('exam', 'credit', 'grading_credit') DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
     IF  InternalIsMapLocked(pDisciplineID) OR
@@ -966,8 +967,8 @@ BEGIN
     # get exam type and extra module ID
     SELECT disciplines.ExamType, modules.ID INTO vOldExamType, vExtraID
         FROM `disciplines`
-        INNER JOIN `modules` ON modules.Type = 'extra' AND
-                                modules.DisciplineID = pDisciplineID
+        INNER JOIN `modules` ON  modules.DisciplineID = pDisciplineID AND
+                                 modules.Type = 'extra'
         WHERE disciplines.ID = pDisciplineID
         LIMIT 1;
     IF vExtraID <= 0 THEN
@@ -980,12 +981,13 @@ BEGIN
         WHERE disciplines.ID = pDisciplineID
         LIMIT 1;
 
-    # this magic check that type change between exam <-> credit/grading_credit
-    IF vOldExamType = 1 XOR pExamType != 'exam' THEN # 1 - exam
+    # check type changing: exam <-> credit/grading_credit
+    IF vOldExamType = 'exam' XOR pExamType != 'exam' THEN
         RETURN 0;
     END IF;
 
 
+    # TODO: extract method addExtraModule
     IF pExamType = 'exam' THEN # change to exam
         SET vExtraMax = 7;
         # count discipline's current max rate
@@ -993,8 +995,8 @@ BEGIN
             FROM `view_disciplines_results`
             WHERE view_disciplines_results.DisciplineID = pDisciplineID
             LIMIT 1;
-        # can't add exam module
-        IF vChecker >= 61 THEN
+
+        IF vChecker >= 61 THEN # can't add exam module ( > 100 points)
             RETURN 1;
         END IF;
         SET vChecker = AddModuleExam(pTeacherID, pDisciplineID);
@@ -1005,7 +1007,7 @@ BEGIN
     ELSE # change to credit
         SET vExtraMax = 29;
         SET vChecker = DeleteModuleExam(pTeacherID, pDisciplineID);
-        # 2 extra submodules (1 created for exam)
+        # 2 extra submodules (1 already created for exam)
         SET vChecker = AddSubmodule(pTeacherID, vExtraID, vExtraMax, '', NULL, 'LandmarkControl');
     END IF;
 
@@ -1017,9 +1019,11 @@ BEGIN
 END //
 
 DROP FUNCTION IF EXISTS ChangeDisciplineHours//
-CREATE FUNCTION `ChangeDisciplineHours`
-    (   `pTeacherID` INT, `pDisciplineID` INT,
-        `pHours` INT, `pType` INT
+CREATE FUNCTION `ChangeDisciplineHours` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pHours` INT,
+        `pType` INT
         # Type: 0 - Practice Hours, 1 - Lecture Hours, 2 - Lab Hours
     )   RETURNS int(11)
     NO SQL
@@ -1051,8 +1055,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS BindGroup//
-CREATE FUNCTION `BindGroup`
-    (`pTeacherID` INT, `pDisciplineID` INT, `pGroupID` INT
+CREATE FUNCTION `BindGroup` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pGroupID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -1076,6 +1082,7 @@ BEGIN
         RETURN 1;
     END IF;
 
+    # TODO: add param SemesterID
     SELECT disciplines.SemesterID INTO vSemesterID
         FROM `disciplines`
         WHERE disciplines.ID = pDisciplineID
@@ -1083,12 +1090,12 @@ BEGIN
 
     # 3. delete students of this group which were bound to discipline before
     DELETE FROM `disciplines_students`
-        WHERE disciplines_students.DisciplineID = pDisciplineID AND
-            disciplines_students.StudentID IN
-                (SELECT students_groups.StudentID
-                    FROM `students_groups`
-                    WHERE   students_groups.GroupID = pGroupID AND
-                            students_groups.SemesterID = vSemesterID
+        WHERE   disciplines_students.DisciplineID = pDisciplineID AND
+                disciplines_students.StudentID IN (
+                    SELECT students_groups.StudentID
+                        FROM `students_groups`
+                        WHERE   students_groups.GroupID = pGroupID AND
+                                students_groups.SemesterID = vSemesterID
                 );
 
     # 4. bind whole group
@@ -1101,20 +1108,25 @@ END //
 
 
 DROP FUNCTION IF EXISTS BindStudent//
-CREATE FUNCTION `BindStudent`
-    (   `pTeacherID` INT, `pDisciplineID` INT, `pStudentID` INT
+CREATE FUNCTION `BindStudent` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pStudentID` INT
     )   RETURNS int(11)
     NO SQL
 BEGIN
-    DECLARE vChecker, vGroupID, vTemp INT DEFAULT -1;
+    DECLARE vChecker, vGroupID, vTemp, vSemesterID INT DEFAULT -1;
     DECLARE vInGroup BOOLEAN DEFAULT FALSE;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
+    SET vSemesterID = GetDisciplineSemesterID(pDisciplineID);
+
     # 1. check if AccessedTeacher is author
     IF NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) THEN
         RETURN -1;
     END IF;
 
+    # TODO: extract method - Get Student Group
     # 2. check if student's group is bound yet
     SET vInGroup = EXISTS(
         SELECT disciplines_groups.ID
@@ -1122,7 +1134,7 @@ BEGIN
             INNER JOIN `disciplines_groups` ON disciplines_groups.DisciplineID = pDisciplineID AND
                                                disciplines_groups.GroupID = students_groups.GroupID
             WHERE students_groups.StudentID = pStudentID AND
-                  students_groups.SemesterID = @CurrentSemesterID
+                  students_groups.SemesterID = vSemesterID
             LIMIT 1
     );
 
@@ -1146,9 +1158,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS UnbindGroup//
-CREATE FUNCTION `UnbindGroup`
-    (   `pTeacherID` INT, `pDisciplineID` INT, `pGroupID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `UnbindGroup` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pGroupID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vSemesterID INT DEFAULT -1;
@@ -1159,11 +1173,11 @@ BEGIN
 
     # detach group from the discipline
     DELETE FROM `disciplines_groups`
-        WHERE disciplines_groups.DisciplineID = pDisciplineID AND
-            disciplines_groups.GroupID = pGroupID
-    LIMIT 1;
-
+        WHERE   disciplines_groups.DisciplineID = pDisciplineID AND
+                disciplines_groups.GroupID = pGroupID
+        LIMIT 1;
 
+    # TODO: add param SemesterID
     SELECT disciplines.SemesterID INTO vSemesterID
         FROM `disciplines`
         WHERE disciplines.ID = pDisciplineID
@@ -1172,33 +1186,41 @@ BEGIN
     # delete attached, and detached (doesn't take disc in any case)
     DELETE FROM `disciplines_students`
     WHERE disciplines_students.DisciplineID = pDisciplineID AND
-          disciplines_students.StudentID IN
-            (SELECT students_groups.StudentID
-             FROM `students_groups`
-             WHERE   students_groups.GroupID = pGroupID AND
-                     students_groups.SemesterID = vSemesterID);
+          disciplines_students.StudentID IN (
+              SELECT students_groups.StudentID
+                 FROM `students_groups`
+                 WHERE  students_groups.GroupID = pGroupID AND
+                        students_groups.SemesterID = vSemesterID
+          );
     RETURN 0;
 END //
 
 
 
 DROP FUNCTION IF EXISTS UnbindStudent//
-CREATE FUNCTION `UnbindStudent`
-    (`pTeacherID` INT, `pDisciplineID` INT, `pStudentID` INT
+CREATE FUNCTION `UnbindStudent` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pStudentID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
-    DECLARE vInGroup INT DEFAULT -1;
+    DECLARE vInGroup, vSemesterID INT DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
     IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) THEN
         RETURN -1;
     END IF;
 
+    SET vSemesterID = GetDisciplineSemesterID(pDisciplineID);
+
+    # TODO: extract method - GetDisciplineSemesterID
+    # TODO: join students_groups by discipline SemesterID
+
     # try to get general group, if student in it.
     SELECT disciplines_groups.ID INTO vInGroup
         FROM `students`
         INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                        students_groups.SemesterID = @CurrentSemesterID
+                                        students_groups.SemesterID = vSemesterID
         INNER JOIN `disciplines_groups` ON disciplines_groups.DisciplineID = pDisciplineID AND
                                            disciplines_groups.GroupID = students_groups.GroupID
         WHERE students.ID = pStudentID
@@ -1227,12 +1249,14 @@ CREATE FUNCTION `Discipline_BindTeacher` (
 ) RETURNS int(11)
     NO SQL
 BEGIN
+    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+  
     # try to insert BindingTeacher in access list
     INSERT INTO `disciplines_teachers`
         (DisciplineID, TeacherID)
         VALUES (pDisciplineID, pBindingTeacherID)
         ON DUPLICATE KEY UPDATE # just stub
-            disciplines_teachers.TeacherID = disciplines_teachers.TeacherID;
+            disciplines_teachers.ID = LAST_INSERT_ID(disciplines_teachers.ID);
     RETURN 0;
 END //
 
@@ -1249,7 +1273,7 @@ BEGIN
     DELETE FROM `disciplines_teachers`
         WHERE   disciplines_teachers.DisciplineID = pDisciplineID AND
                 disciplines_teachers.TeacherID = pBindingTeacher;
-    RETURN 0;
+    RETURN ROW_COUNT()-1;
 END //
 
 
@@ -1262,6 +1286,8 @@ CREATE FUNCTION `Discipline_Delegate` (
 ) RETURNS int(11)
     NO SQL
 BEGIN
+    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
+  
     DECLARE vTemp INT DEFAULT 0;
     SET vTemp = Discipline_BindTeacher(pDisciplineID, pNewAuthorID);
 
@@ -1269,16 +1295,16 @@ BEGIN
         SET disciplines.AuthorID = pNewAuthorID
         WHERE disciplines.ID = pDisciplineID
         LIMIT 1;
-
-    RETURN 0;
+    RETURN ROW_COUNT()-1;
 END //
 
 
 # erase all discipline's rates(and logs), unlock discipline for editing
 DROP FUNCTION IF EXISTS ClearDiscipline//
-CREATE FUNCTION `ClearDiscipline`
-    (   `pAuthorTeacherID` INT, `pDisciplineID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `ClearDiscipline` (
+        `pAuthorTeacherID` INT,
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     IF NOT InternalIsTeacherAuthor(pAuthorTeacherID, pDisciplineID) THEN
@@ -1313,17 +1339,17 @@ END //
 DROP FUNCTION IF EXISTS DeleteDiscipline//
 DROP FUNCTION IF EXISTS Discipline_Delete//
 CREATE FUNCTION `Discipline_Delete` (
-    `pDisciplineID` INT
-) RETURNS int(11)
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     # delete roadmap
     DELETE FROM `submodules`
-        WHERE submodules.ModuleID IN
-            (SELECT modules.ID
+        WHERE submodules.ModuleID IN (
+            SELECT modules.ID
                 FROM `modules`
                 WHERE modules.DisciplineID = pDisciplineID
-            );
+        );
     DELETE FROM `modules`
         WHERE modules.DisciplineID = pDisciplineID;
 
@@ -1348,8 +1374,8 @@ END //
 DROP FUNCTION IF EXISTS CountRatings//
 DROP FUNCTION IF EXISTS Discipline_CountRatings//
 CREATE FUNCTION `Discipline_CountRatings` (
-    `pDisciplineID` INT
-)   RETURNS int(11)
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vRes INT DEFAULT 0;
@@ -1368,9 +1394,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS RestrictAfterMilestone//
-CREATE FUNCTION `RestrictAfterMilestone`
-    (   `pTeacherID` INT, `pDisciplineID` INT, `pMilestone` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `RestrictAfterMilestone` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
+        `pMilestone` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     UPDATE `disciplines`
@@ -1383,18 +1411,20 @@ END //
 
 
 DROP FUNCTION IF EXISTS RestrictAfterMilestoneForCredits//
-CREATE FUNCTION `RestrictAfterMilestoneForCredits`  (   `pTeacherID` INT,
-                                                        `pFacultyID` INT,
-                                                        `pMilestone` INT
-                                                    )   RETURNS int(11)
+CREATE FUNCTION `RestrictAfterMilestoneForCredits` (
+        `pTeacherID` INT,
+        `pFacultyID` INT,
+        `pMilestone` INT,
+        `pSemesterID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     UPDATE `disciplines`
         SET disciplines.MilestoneDate = CURDATE(),
             disciplines.Milestone = pMilestone
-        WHERE   disciplines.SemesterID = @CurrentSemesterID AND
-                ( disciplines.ExamType = 'credit' OR disciplines.ExamType = 'grading_credit') AND
-                disciplines.FacultyID= pFacultyID;
+        WHERE    disciplines.FacultyID= pFacultyID AND
+                disciplines.SemesterID = pSemesterID AND
+                ( disciplines.ExamType = 'credit' OR disciplines.ExamType = 'grading_credit');
     RETURN 0;
 END //
 
@@ -1406,10 +1436,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeModuleName//
-CREATE FUNCTION `ChangeModuleName`
-    (   `pTeacherID` INT, `pModuleID` INT,
+CREATE FUNCTION `ChangeModuleName` (
+        `pTeacherID` INT,
+        `pModuleID` INT,
         `pName` VARCHAR(200) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     UPDATE `modules`
@@ -1424,8 +1455,9 @@ END //
 
 
 DROP FUNCTION IF EXISTS AddModule//
-CREATE FUNCTION `AddModule`
-    (   `pTeacherID` INT, `pDisciplineID` INT,
+CREATE FUNCTION `AddModule` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
         `pName` VARCHAR(200) CHARSET utf8
     ) RETURNS int(11)
     NO SQL
@@ -1457,9 +1489,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS AddModuleExam//
-CREATE FUNCTION `AddModuleExam`
-    (`pTeacherID` INT, `pDisciplineID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `AddModuleExam` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vChecker, vModule INT DEFAULT -1;
@@ -1469,6 +1502,7 @@ BEGIN
         RETURN -1;
     END IF;
 
+    # TODO: exists
     # check exam module existence
     SELECT modules.ID
         INTO vChecker
@@ -1493,8 +1527,9 @@ END //
 
 
 DROP FUNCTION IF EXISTS AddModuleExtra//
-CREATE FUNCTION `AddModuleExtra`
-    (   `pTeacherID` INT, `pDisciplineID` INT
+CREATE FUNCTION `AddModuleExtra` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -1548,9 +1583,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS DeleteModule//
-CREATE FUNCTION `DeleteModule`
-    (   `pTeacherID` INT, `pModuleID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `DeleteModule` (
+        `pTeacherID` INT,
+        `pModuleID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vDisciplineID INT DEFAULT -1;
@@ -1589,9 +1625,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS DeleteModuleExam//
-CREATE FUNCTION `DeleteModuleExam`
-    (   `pTeacherID` INT, `pDisciplineID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `DeleteModuleExam` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vExamModuleID INT DEFAULT -1;
@@ -1623,9 +1660,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS SwapModuleOrder//
-CREATE FUNCTION `SwapModuleOrder`
-    (   `pTeacherID` INT, `pModuleID1` INT, `pModuleID2` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `SwapModuleOrder` (
+        `pTeacherID` INT,
+        `pModuleID1` INT,
+        `pModuleID2` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vChecker, vOrder1, vOrder2,
@@ -1678,9 +1717,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS AddModuleBonus//
-CREATE FUNCTION `AddModuleBonus`
-    (   `pTeacherID` INT, `pDisciplineID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `AddModuleBonus` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
+    )   RETURNS INT(11)
     NO SQL
 BEGIN
     DECLARE vChecker, vModuleID INT DEFAULT -1;
@@ -1710,8 +1750,9 @@ END //
 
 
 DROP FUNCTION IF EXISTS DeleteModuleBonus//
-CREATE FUNCTION `DeleteModuleBonus`
-    (   `pTeacherID` INT, `pDisciplineID` INT
+CREATE FUNCTION `DeleteModuleBonus` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -1750,12 +1791,12 @@ END //
 # -------------------------------------------------------------------------------------------
 
 DROP FUNCTION IF EXISTS ChangeSubmoduleMaxAndControl//
-CREATE FUNCTION `ChangeSubmoduleMaxAndControl`
-    (   `pTeacherID`     INT,
+CREATE FUNCTION `ChangeSubmoduleMaxAndControl` (
+        `pTeacherID`     INT,
         `pSubmoduleID`   INT,
         `pMaxRate`       INT,
         `pControlType`   VARCHAR(30) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vChecker, vDisciplineID, vIsLocked, vNewDiscMaxRate, vCurRate INT DEFAULT -1;
@@ -1788,11 +1829,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeSubmoduleName//
-CREATE FUNCTION `ChangeSubmoduleName`
-    (   `pTeacherID` INT,
+CREATE FUNCTION `ChangeSubmoduleName` (
+        `pTeacherID` INT,
         `pSubmoduleID` INT,
         `pName` VARCHAR(200) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vIsLocked INT DEFAULT -1;
@@ -1818,11 +1859,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeSubmoduleDescription//
-CREATE FUNCTION `ChangeSubmoduleDescription`
-    (   `pTeacherID` INT,
+CREATE FUNCTION `ChangeSubmoduleDescription` (
+        `pTeacherID` INT,
         `pSubmoduleID` INT,
         `pDescription` VARCHAR(200) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vIsLocked INT DEFAULT -1;
@@ -1849,8 +1890,9 @@ END //
 
 
 DROP FUNCTION IF EXISTS DeleteSubmodule//
-CREATE FUNCTION `DeleteSubmodule`
-    (   `pTeacherID` INT, `pSubmoduleID` INT
+CREATE FUNCTION `DeleteSubmodule` (
+        `pTeacherID` INT,
+        `pSubmoduleID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -1887,12 +1929,14 @@ END //
 
 
 DROP FUNCTION IF EXISTS AddSubmodule//
-CREATE FUNCTION `AddSubmodule`
-    (   `pTeacherID` INT, `pModuleID` INT, `pMaxRate` INT,
+CREATE FUNCTION `AddSubmodule` (
+        `pTeacherID` INT,
+        `pModuleID` INT,
+        `pMaxRate` INT,
         `pName` VARCHAR(200) CHARSET utf8,
         `pDescription` VARCHAR(200) CHARSET utf8,
         `pControlType` VARCHAR(30) CHARSET utf8
-    )   RETURNS int(11)
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vOrderNum, vIsLocked INT DEFAULT -1;
@@ -1936,8 +1980,11 @@ END //
 
 
 DROP FUNCTION IF EXISTS SwapSubmoduleOrder//
-CREATE FUNCTION `SwapSubmoduleOrder`
-(   `pTeacherID` INT, `pSubmoduleID1` INT, `pSubmoduleID2` INT  ) RETURNS int(11)
+CREATE FUNCTION `SwapSubmoduleOrder` (
+        `pTeacherID` INT,
+        `pSubmoduleID1` INT,
+        `pSubmoduleID2` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vDisciplineID, vOrder1, vOrder2,
@@ -1994,8 +2041,9 @@ END //
 
 # TODO: kill
 DROP FUNCTION IF EXISTS GetMaxRateForDisc//
-CREATE FUNCTION `GetMaxRateForDisc`
-(   `pDisciplineID` INT  )   RETURNS int(11)
+CREATE FUNCTION `GetMaxRateForDisc` (
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vResult INT DEFAULT 0;
@@ -2014,8 +2062,10 @@ END //
 
 # Вычисление максимального балла для submodule
 DROP FUNCTION IF EXISTS CalculateMaxRateForExtra//
-CREATE FUNCTION `CalculateMaxRateForExtra`
-( `pSubmoduleID` INT, `pStudentID` INT) RETURNS int(11)
+CREATE FUNCTION `CalculateMaxRateForExtra` (
+        `pSubmoduleID` INT,
+        `pStudentID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vExamType INT DEFAULT -1; # enum('exam', 'credit');# utf8;
@@ -2049,26 +2099,27 @@ END //
 
 
 DROP FUNCTION IF EXISTS SetStudentRate//
-CREATE FUNCTION `SetStudentRate`
-    (   `pTeacherID` INT,
+CREATE FUNCTION `SetStudentRate` (
+        `pTeacherID` INT,
         `pStudentID` INT,
         `pSubmoduleID` INT,
         `pRate` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
-    DECLARE vDisciplineID, vMaxRate, vModuleType INT DEFAULT -1;
+    DECLARE vDisciplineID, vMaxRate, vModuleType, vSemesterID INT DEFAULT -1;
     DECLARE vIsOver, vIsLocked, vIsUsed BOOLEAN DEFAULT FALSE;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
     SET vIsOver = TRUE;
     SELECT  disciplines.ID,
+            disciplines.SemesterID,
             disciplines.isLocked,
             disciplines.Milestone,
             submodules.IsUsed,
             submodules.maxRate,
             modules.Type
-        INTO vDisciplineID, vIsLocked, vIsOver, vIsUsed, vMaxRate, vModuleType
+        INTO vDisciplineID, vSemesterID, vIsLocked, vIsOver, vIsUsed, vMaxRate, vModuleType
         FROM `submodules`
         INNER JOIN `modules`                ON  submodules.ModuleID = modules.ID
         INNER JOIN `disciplines`            ON  modules.DisciplineID = disciplines.ID
@@ -2083,8 +2134,8 @@ BEGIN
     # 1) check rights
     # 2) check, you can't rate regular and bonus after milestone
     # 3) check, max rate exceeding
-    IF  NOT InternalIsStudentAttached(pStudentID, vDisciplineID) OR
-        NOT InternalIsTeacherBounded(pTeacherID, vDisciplineID) OR
+    IF  NOT InternalIsStudentAttached(pStudentID, vDisciplineID, vSemesterID) OR
+        NOT InternalIsTeacherBound(pTeacherID, vDisciplineID) OR
         pRate > vMaxRate OR
         (vIsOver AND (vModuleType = 1 OR vModuleType = 3)) # 1 - regular, 3 - bonus
     THEN
@@ -2136,8 +2187,9 @@ END //
 
 
 DROP FUNCTION IF EXISTS SetRequestStatus//
-CREATE FUNCTION `SetRequestStatus`
-    (`pRequestID` INT, `pStatus` VARCHAR(20) CHARSET utf8
+CREATE FUNCTION `SetRequestStatus` (
+        `pRequestID` INT,
+        `pStatus` VARCHAR(20) CHARSET utf8
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -2175,10 +2227,10 @@ END//
 
 
 DROP FUNCTION IF EXISTS CreateRecoveryToken//
-CREATE FUNCTION `CreateRecoveryToken`
-    (   `pAccountOrEMail` VARCHAR(255) CHARSET utf8,
+CREATE FUNCTION `CreateRecoveryToken` (
+        `pAccountOrEMail` VARCHAR(255) CHARSET utf8,
         `pToken` VARCHAR(100) CHARSET utf8
-    )   RETURNS VARCHAR(255) charset utf8
+    ) RETURNS VARCHAR(255) charset utf8
     NO SQL
 BEGIN
     DECLARE vAccountID INT DEFAULT -1;
@@ -2214,37 +2266,40 @@ BEGIN
 END//
 
 DROP FUNCTION IF EXISTS GetUserFullNameByAccountID//
-CREATE FUNCTION `GetUserFullNameByAccountID`
-    (   `pAccountID` INT(11))   RETURNS VARCHAR(255) charset utf8
+CREATE FUNCTION `GetUserFullNameByAccountID` (
+        `pAccountID` INT(11)
+    ) RETURNS VARCHAR(255) charset utf8
 NO SQL
 BEGIN
     DECLARE vUserFullName VARCHAR(255) charset utf8;
     DECLARE vChecker INT DEFAULT -1;
 
-    SELECT students.ID As ID, CONCAT(students.LastName,' ',students.FirstName,' ',students.SecondName) As UserName
-    INTO vChecker, vUserFullName
-    FROM `students`
-    WHERE students.AccountID = pAccountID
-    LIMIT 1;
-
-    IF vChecker <= 0 THEN
-    SELECT teachers.ID As ID, CONCAT(teachers.LastName,' ',teachers.FirstName,' ',teachers.SecondName) As UserName
-    INTO vChecker, vUserFullName
-    FROM `teachers`
-    WHERE teachers.AccountID = pAccountID
-    LIMIT 1;
-
-    IF vChecker <= 0 THEN
-      RETURN '';
-    END IF;
+    # try to find student with that account id
+    SELECT students.ID, CONCAT(students.LastName,' ',students.FirstName,' ',students.SecondName)
+        INTO vChecker, vUserFullName
+        FROM `students`
+        WHERE students.AccountID = pAccountID
+        LIMIT 1;
+
+    IF vChecker <= 0 THEN # try to find teacher with that account id
+        SELECT teachers.ID, CONCAT(teachers.LastName,' ',teachers.FirstName,' ',teachers.SecondName)
+            INTO vChecker, vUserFullName
+            FROM `teachers`
+            WHERE teachers.AccountID = pAccountID
+            LIMIT 1;
+
+        IF vChecker <= 0 THEN
+          RETURN '';
+        END IF;
     END IF;
 
     RETURN vUserFullName;
 END//
 
 DROP FUNCTION IF EXISTS UseRecoveryToken//
-CREATE FUNCTION `UseRecoveryToken`
-(   `pToken` VARCHAR(100) CHARSET utf8) RETURNS int(11)
+CREATE FUNCTION `UseRecoveryToken` (
+        `pToken` VARCHAR(100) CHARSET utf8
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE vChecker INT DEFAULT -1;
@@ -2258,7 +2313,11 @@ BEGIN
 END//
 
 DROP FUNCTION IF EXISTS SaveSession //
-CREATE FUNCTION SaveSession(pSessionID VARCHAR(40), pUserLogin VARCHAR(50) CHARSET utf8, pUserPassword VARCHAR(64)) RETURNS INT(11)
+CREATE FUNCTION SaveSession
+    (   pSessionID VARCHAR(40),
+        pUserLogin VARCHAR(50) CHARSET utf8,
+        pUserPassword VARCHAR(64)
+    ) RETURNS INT(11)
     NO SQL
 BEGIN
     INSERT INTO sessions (SessionID, Login, Password)
diff --git a/db/StoredProcedures.sql b/db/StoredProcedures.sql
index 36a66ad5b371b44afd1fdd48b2dbc72fb7c80def..d7aedae59de5e69aa035c95aed79bda98fef1a94 100644
--- a/db/StoredProcedures.sql
+++ b/db/StoredProcedures.sql
@@ -18,6 +18,7 @@ DROP PROCEDURE IF EXISTS GetMapForStudentExam//
 DROP PROCEDURE IF EXISTS GetRatesForStudentsGroup//
 
 DROP PROCEDURE IF EXISTS CreateFaculty //
+DROP PROCEDURE IF EXISTS GetReports//
 
 
 # -------------------------------------------------------------------------------------------
@@ -239,7 +240,10 @@ END //
 
 
 DROP PROCEDURE IF EXISTS GetPersonalInfo//
-CREATE PROCEDURE `GetPersonalInfo` ( IN `pUserID` INT )
+CREATE PROCEDURE `GetPersonalInfo` (
+        IN `pUserID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     DECLARE vAccountType INT DEFAULT -1;
@@ -270,7 +274,7 @@ BEGIN
                 view_students.FacultyAbbr
             FROM `view_students`
             WHERE view_students.AccountID = pUserID AND
-                  view_students.SemesterID = @CurrentSemesterID
+                  view_students.SemesterID = pSemesterID
             LIMIT 1;
     ELSE
         SELECT  view_teachers.LastName,
@@ -397,7 +401,10 @@ END //
 
 DROP PROCEDURE IF EXISTS GetStudentsByStudyGroups//
 DROP PROCEDURE IF EXISTS GetStudents//
-CREATE PROCEDURE `GetStudents`  (IN `pGroupID` INT)
+CREATE PROCEDURE `GetStudents`  (
+        IN `pGroupID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT  view_students.StudentID AS 'ID',
@@ -412,7 +419,7 @@ BEGIN
             view_students.GroupNum
         FROM `view_students`
         WHERE view_students.GroupID = pGroupID AND
-              view_students.SemesterID = @CurrentSemesterID
+              view_students.SemesterID = pSemesterID
         ORDER BY view_students.LastName ASC, view_students.FirstName ASC;
 END //
 
@@ -421,7 +428,8 @@ DROP PROCEDURE IF EXISTS GetStudentsByFaculty//
 CREATE PROCEDURE `GetStudentsByFaculty`
     (   IN `pFacultyID` INT,
         IN `pGradeID` INT,
-        IN `pGroupID` INT
+        IN `pGroupID` INT,
+        IN `pSemesterID` INT
     )
     NO SQL
 BEGIN
@@ -437,7 +445,7 @@ BEGIN
             view_students.GroupNum
     FROM `view_students`
     WHERE view_students.FacultyID = pFacultyID AND
-          view_students.SemesterID = @CurrentSemesterID AND
+          view_students.SemesterID = pSemesterID AND
           (pGradeID = 0 OR view_students.GradeID = pGradeID) AND
           (pGroupID = 0 OR view_students.GroupID = pGroupID)
     ORDER BY view_students.LastName ASC, view_students.FirstName ASC;
@@ -446,10 +454,14 @@ END //
 
 # students, that don't included in general groups without attached
 DROP PROCEDURE IF EXISTS SearchStudents//
-CREATE PROCEDURE `SearchStudents`
-    (   IN `pGradeID` INT, IN `pGroupID` INT, IN `pFacultyID` INT,
+CREATE PROCEDURE `SearchStudents` (
+        IN `pGradeID` INT,
+        IN `pGroupID` INT,
+        IN `pFacultyID` INT,
         IN `pFullName` VARCHAR(100) CHARSET utf8,
-        IN `pDisciplineID` INT)
+        IN `pDisciplineID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT  view_students.StudentID AS 'ID',
@@ -466,7 +478,7 @@ BEGIN
                                             disciplines_students.DisciplineID = pDisciplineID
         LEFT JOIN `disciplines_groups` ON   disciplines_groups.GroupID = view_students.GroupID AND
                                             disciplines_groups.DisciplineID = pDisciplineID
-        WHERE   view_students.SemesterID = @CurrentSemesterID AND
+        WHERE   view_students.SemesterID = pSemesterID AND
                 view_students.FacultyID = pFacultyID AND
                 view_students.GradeID = pGradeID AND
                 (view_students.GroupID = pGroupID OR pGroupID = 0) AND
@@ -482,8 +494,10 @@ END //
 
 # all students in general groups, that take course (with attached and detached)
 DROP PROCEDURE IF EXISTS GetStudentsForDiscipline//
-CREATE PROCEDURE `GetStudentsForDiscipline`
-    (   IN `pDisciplineID` INT)
+CREATE PROCEDURE `GetStudentsForDiscipline` (
+        IN `pDisciplineID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT  view_disciplines_students.StudentID AS 'ID',
@@ -498,7 +512,7 @@ BEGIN
             view_disciplines_students.AttachType AS 'AttachType'
     FROM `view_disciplines_students`
     WHERE view_disciplines_students.DisciplineID = pDisciplineID AND
-          view_disciplines_students.SemesterID = @CurrentSemesterID
+          view_disciplines_students.SemesterID = pSemesterID
     ORDER BY    (view_disciplines_students.AttachType IS NULL OR
                     view_disciplines_students.AttachType = 'detach') DESC,
         view_disciplines_students.GradeID ASC,
@@ -511,8 +525,10 @@ END //
 
 # all students takes that course (general groups + attached)
 DROP PROCEDURE IF EXISTS GetStudentsForRating//
-CREATE PROCEDURE `GetStudentsForRating`
-    (   IN `pDisciplineID` INT)
+CREATE PROCEDURE `GetStudentsForRating` (
+        IN `pDisciplineID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT  view_disciplines_students.StudentID AS 'ID',
@@ -526,7 +542,7 @@ BEGIN
             view_disciplines_students.GroupNum,
             (view_disciplines_students.AttachType IS NOT NULL) AS 'IsAttached'
     FROM `view_disciplines_students`
-    WHERE   view_disciplines_students.SemesterID = @CurrentSemesterID AND
+    WHERE   view_disciplines_students.SemesterID = pSemesterID AND
             view_disciplines_students.DisciplineID = pDisciplineID AND
             (view_disciplines_students.AttachType IS NULL OR
                 view_disciplines_students.AttachType = 'attach')
@@ -581,7 +597,10 @@ NO SQL
 # TODO: haven't reference on it
 # all disciplines for faculty in current semester
 DROP PROCEDURE IF EXISTS GetDisciplines//
-CREATE PROCEDURE `GetDisciplines` (  IN `pFacultyID` INT )
+CREATE PROCEDURE `GetDisciplines` (
+        IN `pFacultyID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT  view_disciplines.DisciplineID   AS 'ID',
@@ -592,7 +611,7 @@ BEGIN
         FROM `view_disciplines`
         INNER JOIN `view_disciplines_results`
             ON view_disciplines_results.DisciplineID = view_disciplines.DisciplineID
-        WHERE view_disciplines.SemesterID = @CurrentSemesterID AND
+        WHERE view_disciplines.SemesterID = pSemesterID AND
             view_disciplines.FacultyID = pFacultyID
         ORDER BY view_disciplines.SubjectName ASC;
 END //
@@ -602,7 +621,10 @@ END //
 # processed format of output (after desequentialization)
 # { discipline1 {group1, group2, ...}, discipline2 {groupN, ...}, ... }
 DROP PROCEDURE IF EXISTS GetDisciplinesForTeacher//
-CREATE PROCEDURE `GetDisciplinesForTeacher`(IN `pTeacherID` INT)
+CREATE PROCEDURE `GetDisciplinesForTeacher` (
+        IN `pTeacherID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT DISTINCT view_disciplines.DisciplineID AS 'ID',
@@ -626,7 +648,7 @@ BEGIN
     LEFT JOIN `view_disciplines` ON disciplines_teachers.DisciplineID = view_disciplines.DisciplineID
     LEFT JOIN `view_disciplines_results` ON view_disciplines_results.DisciplineID = view_disciplines.DisciplineID
     WHERE disciplines_teachers.TeacherID = pTeacherID AND
-            view_disciplines.SemesterID = @CurrentSemesterID
+            view_disciplines.SemesterID = pSemesterID
     ORDER BY    view_disciplines.GradeID ASC,
                 view_disciplines.SubjectName ASC,
                 view_disciplines.DisciplineID ASC,
@@ -636,7 +658,10 @@ END //
 
 # get all disciplines, that student take.
 DROP PROCEDURE IF EXISTS GetDisciplinesForStudent//
-CREATE PROCEDURE `GetDisciplinesForStudent`(IN `pStudentID` INT)
+CREATE PROCEDURE `GetDisciplinesForStudent` (
+        IN `pStudentID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     SELECT  view_disciplines.DisciplineID     AS 'ID',
@@ -657,8 +682,8 @@ BEGIN
         LEFT JOIN `view_rating_result` ON  view_rating_result.StudentID = pStudentID AND
                                             view_rating_result.DisciplineID = view_disciplines_results.DisciplineID
         INNER JOIN `view_teachers` ON view_teachers.TeacherID = view_disciplines.AuthorID
-        WHERE   view_disciplines_students.SemesterID = @CurrentSemesterID AND
-                view_disciplines.SemesterID = @CurrentSemesterID AND
+        WHERE   view_disciplines_students.SemesterID = pSemesterID AND
+                view_disciplines.SemesterID = pSemesterID AND
                 view_disciplines_students.StudentID = pStudentID AND
                 (view_disciplines_students.AttachType IS NULL OR view_disciplines_students.AttachType != 'detach')
         ORDER BY view_disciplines.ExamType ASC, view_disciplines.SubjectName ASC;
@@ -667,7 +692,10 @@ END //
 
 # get all disciplines for group, including disciplines, where students have attached status
 DROP PROCEDURE IF EXISTS GetDisciplinesForGroup//
-CREATE PROCEDURE `GetDisciplinesForGroup`(IN `pGroupID` INT)
+CREATE PROCEDURE `GetDisciplinesForGroup` (
+        IN `pGroupID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
     (SELECT view_disciplines.DisciplineID  AS 'ID',
@@ -676,7 +704,7 @@ BEGIN
             view_disciplines.ExamType      AS 'type'
         FROM `disciplines_groups`
         INNER JOIN `view_disciplines` ON    view_disciplines.DisciplineID = disciplines_groups.DisciplineID AND
-                                            view_disciplines.SemesterID = @CurrentSemesterID
+                                            view_disciplines.SemesterID = pSemesterID
         WHERE disciplines_groups.GroupID = pGroupID
     ) UNION DISTINCT
     (SELECT view_disciplines.DisciplineID  AS 'ID',
@@ -686,9 +714,9 @@ BEGIN
         FROM `disciplines_students`
         INNER JOIN `students` ON disciplines_students.StudentID = students.ID
         INNER JOIN `view_disciplines` ON view_disciplines.DisciplineID = disciplines_students.DisciplineID AND
-                                         view_disciplines.SemesterID = @CurrentSemesterID
+                                         view_disciplines.SemesterID = pSemesterID
         INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                        students_groups.SemesterID = @CurrentSemesterID
+                                        students_groups.SemesterID = pSemesterID
         WHERE students_groups.GroupID = pGroupID
     );
 END //
@@ -700,17 +728,23 @@ END //
 # -------------------------------------------------------------------------------------------
 
 DROP PROCEDURE IF EXISTS GetRatesForGroup//
-CREATE PROCEDURE `GetRatesForGroup`
-    (   IN `pDisciplineID` INT, IN `pGroupID` INT)
+CREATE PROCEDURE `GetRatesForGroup` (
+    IN `pDisciplineID` INT,
+    IN `pGroupID` INT
+)
     NO SQL
 BEGIN
     DECLARE vChecker BOOLEAN DEFAULT FALSE;
+    DECLARE vSemesterID INT DEFAULT -1;
+
     SELECT disciplines_groups.ID IS NOT NULL INTO vChecker
         FROM `disciplines_groups`
         WHERE disciplines_groups.DisciplineID = pDisciplineID AND
               disciplines_groups.GroupID = pGroupID
         LIMIT 1;
 
+    SET vSemesterID = GetDisciplineSemesterID(pDisciplineID);
+
     IF !vChecker THEN
         SELECT  students.ID,
             students.LastName,
@@ -723,7 +757,7 @@ BEGIN
             LEFT JOIN `view_rating_result` ON view_rating_result.DisciplineID = pDisciplineID AND
                                               view_rating_result.StudentID = students.ID
             INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                            students_groups.SemesterID = @CurrentSemesterID
+                                            students_groups.SemesterID = vSemesterID
         WHERE students_groups.GroupID = pGroupID AND
               EXISTS(SELECT * FROM `disciplines_students`
               WHERE  disciplines_students.DisciplineID = pDisciplineID AND
@@ -742,7 +776,7 @@ BEGIN
             LEFT JOIN `view_rating_result` ON view_rating_result.DisciplineID = pDisciplineID AND
                                                view_rating_result.StudentID = students.ID
             INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                            students_groups.SemesterID = @CurrentSemesterID
+                                            students_groups.SemesterID = vSemesterID
             WHERE students_groups.GroupID = pGroupID AND
                   NOT EXISTS(SELECT * FROM `disciplines_students`
                                 WHERE  disciplines_students.DisciplineID = pDisciplineID AND
@@ -854,18 +888,21 @@ BEGIN
 END //
 
 DROP PROCEDURE IF EXISTS GetAttestationData//
-CREATE PROCEDURE `GetAttestationData`
-    (   IN `pDisciplineID` INT, IN `pGroupID` INT)
+CREATE PROCEDURE `GetAttestationData` (
+        IN `pDisciplineID` INT,
+        IN `pGroupID` INT,
+        IN `pSemesterID` INT
+    )
     NO SQL
 BEGIN
-    SELECT    students.ID 	AS 'StudentID',
+    SELECT    students.ID   AS 'StudentID',
               rating_table.Rate As 'Rate',
               rating_table.Date As 'Date',
               submodules.OrderNum As 'OrderNum',
               modules.Type As 'Type'
         FROM `students`
         INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                        students_groups.SemesterID = @CurrentSemesterID
+                                        students_groups.SemesterID = pSemesterID
 
         LEFT JOIN `disciplines_groups` ON   disciplines_groups.DisciplineID = pDisciplineID AND
                                             disciplines_groups.GroupID = students_groups.GroupID
@@ -1016,42 +1053,12 @@ END //
 
 
 
-# TODO: kill GetRateForDisc
-DROP PROCEDURE IF EXISTS GetReports//
-CREATE PROCEDURE `GetReports` (IN `pGroupID` INT)
-    NO SQL
-BEGIN
-    SELECT  students.ID AS 'StudentID',
-            students.LastName,
-            students.FirstName,
-            students.SecondName,
-            disciplines.ID,
-            GetRateForDisc(students.ID, disciplines.ID) AS 'Rate',
-            GetMaxRateForDisc(disciplines.ID) AS 'MaxRate'
-        FROM `students`
-        LEFT JOIN `disciplines` ON disciplines.ID IN
-            (
-                SELECT disciplines_groups.DisciplineID
-                    FROM `disciplines_groups`
-                    WHERE disciplines_groups.GroupID = pGroupID
-                    UNION DISTINCT
-                    SELECT disciplines_students.DisciplineID
-                    FROM `disciplines_students`
-                    INNER JOIN `students` ON disciplines_students.ID = students.ID
-                    INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                                    students_groups.SemesterID = @CurrentSemesterID
-                    WHERE students_groups.GroupID = pGroupID
-            )
-        INNER JOIN `subjects` ON disciplines.SubjectID = subjects.ID
-        INNER JOIN `students_groups` ON students_groups.StudentID = students.ID AND
-                                        students_groups.SemesterID = @CurrentSemesterID
-        WHERE students_groups.GroupID = pGroupID;
-END //
-
 
 DROP PROCEDURE IF EXISTS GetFinalFormInfo//
-CREATE PROCEDURE `GetFinalFormInfo`
-(IN `pDisciplineID` INT, IN `pGroupID` INT)
+CREATE PROCEDURE `GetFinalFormInfo` (
+    IN `pDisciplineID` INT,
+    IN `pGroupID` INT
+)
     NO SQL
 BEGIN
     SELECT  study_groups.GroupNum AS 'GroupNum',
@@ -1088,20 +1095,20 @@ BEGIN
         INNER JOIN `teachers` ON teachers.ID = disciplines.AuthorID
         INNER JOIN `departments` ON departments.ID = teachers.DepartmentID
         INNER JOIN `job_positions` ON job_positions.ID = teachers.JobPositionID
-        INNER JOIN `semesters` ON semesters.ID = @CurrentSemesterID
+        INNER JOIN `semesters` ON disciplines.SemesterID
         WHERE study_groups.ID = pGroupID
         LIMIT 1;
 END //
 
 DROP PROCEDURE IF EXISTS GetSession //
 CREATE PROCEDURE GetSession (IN pID INT(11), OUT pSessionID VARCHAR(40), OUT pUserLogin VARCHAR(50) CHARSET utf8, OUT pUserPassword VARCHAR(64))
-	NO SQL
+    NO SQL
 BEGIN
 
-	SELECT SessionID, Login, Password 
-		INTO pSessionID, pUserLogin, pUserPassword
-		FROM sessions
-		WHERE sessions.ID=pID;
+    SELECT SessionID, Login, Password
+        INTO pSessionID, pUserLogin, pUserPassword
+        FROM sessions
+        WHERE sessions.ID=pID;
 END //
 
 DELIMITER ;
\ No newline at end of file
diff --git a/~dev_rating/application/classes/Model/Discipline.php b/~dev_rating/application/classes/Model/Discipline.php
index 0891b61f980aae7bd333770f5fdf6128111d69d0..3420f79599cf6acd30b77c1e1cc0c3b17db33f12 100644
--- a/~dev_rating/application/classes/Model/Discipline.php
+++ b/~dev_rating/application/classes/Model/Discipline.php
@@ -268,7 +268,8 @@ class Model_Discipline extends Model implements JsonSerializable, ArrayAccess
      * @return Database_Result
      */
     public static function setMilestoneForCredits($teacherID, $facultyID, $milestone) {
-        $sql = "SELECT `RestrictAfterMilestoneForCredits`('$teacherID', '$facultyID', '$milestone') AS 'Num'";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "SELECT `RestrictAfterMilestoneForCredits`('$teacherID', '$facultyID', '$milestone', $semesterID) AS 'Num'";
         return DB::query(Database::SELECT, $sql)->execute();
     }
 
diff --git a/~dev_rating/application/classes/Model/Faculty.php b/~dev_rating/application/classes/Model/Faculty.php
index df40851857948aab74052b638a8904be5c730efa..15b6caf5c7eccf155c2bfb1148c96686414209dc 100644
--- a/~dev_rating/application/classes/Model/Faculty.php
+++ b/~dev_rating/application/classes/Model/Faculty.php
@@ -12,9 +12,11 @@ class Model_Faculty extends Model
 
     /** @return Model_Discipline[] */
     public function getDisciplines() {
-        $sql = "CALL `GetDisciplines`(:id)";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetDisciplines`(:id, :semesterID)";
         $query = DB::query(Database::SELECT, $sql)
             ->param(':id', $this->id)
+            ->param(':semesterID', $semesterID)
             ->execute();
 
         $list = [];
diff --git a/~dev_rating/application/classes/Model/Group.php b/~dev_rating/application/classes/Model/Group.php
index 6c2ee428945fd057d5743ace623c593d4eb2d7b5..de8cfd689e6a6d27a5aabd9504b867653db4115d 100644
--- a/~dev_rating/application/classes/Model/Group.php
+++ b/~dev_rating/application/classes/Model/Group.php
@@ -12,9 +12,11 @@ class Model_Group extends Model
 
     /** @return Model_Discipline[] */
     public function getDisciplines($lazy = true) {
-        $sql = "CALL `GetDisciplinesForGroup`(:id)";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetDisciplinesForGroup`(:id, :semesterID)";
         $query = DB::query(Database::SELECT, $sql)
             ->param(':id', $this->id)
+            ->param(':semesterID', $semesterID)
             ->execute();
 
         $list = [];
diff --git a/~dev_rating/application/classes/Model/Rating.php b/~dev_rating/application/classes/Model/Rating.php
index 0d9c95d1b2d7e6760e440a9367e94e2ea280f50a..31909b370073c4f30d96840fbee8f9926dfc9cd5 100644
--- a/~dev_rating/application/classes/Model/Rating.php
+++ b/~dev_rating/application/classes/Model/Rating.php
@@ -3,7 +3,8 @@
 class Model_Rating extends Model
 {
     public static function GetStudentsForRating($disciplineID) {
-        $sql = "CALL `GetStudentsForRating`('$disciplineID'); ";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetStudentsForRating`('$disciplineID', $semesterID); ";
         return DB::query(Database::SELECT, $sql)->execute();
     }
 
@@ -50,7 +51,8 @@ class Model_Rating extends Model
 
     public static function getAttestationData($disciplineID, $groupID)
     {
-        $sql = "CALL `GetAttestationData`($disciplineID, $groupID)";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetAttestationData`($disciplineID, $groupID, $semesterID)";
         return DB::query(Database::SELECT, $sql)->execute();
     }
 
diff --git a/~dev_rating/application/classes/Model/Student.php b/~dev_rating/application/classes/Model/Student.php
index 73720128c3dd70e5830e547948a989252c42a3ba..5aaccce865b38b176cdf225c5282944d0346a011 100644
--- a/~dev_rating/application/classes/Model/Student.php
+++ b/~dev_rating/application/classes/Model/Student.php
@@ -12,9 +12,11 @@ class Model_Student extends Model
 
     /** @return Model_Discipline[] */
     public function getDisciplines() {
-        $sql = "CALL `GetDisciplinesForStudent`(:id);";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetDisciplinesForStudent`(:id, :semesterID);";
         $query = DB::query(Database::SELECT, $sql)
             ->param(':id', $this->id)
+            ->param(':semesterID', $semesterID)
             ->execute();
 
         $list = [];
@@ -95,10 +97,13 @@ class Model_Student extends Model
      * @return $this;
      */
     public function toAcademicLeave() {
-        $sql = "CALL `ControlStudentGroup`(:id, -1, true);";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `ControlStudentGroup`(:id, -1, true, :semesterID);";
+
 
         DB::query(Database::SELECT, $sql)
             ->param(':id', $this->id)
+            ->param(':semesterID', $semesterID)
             ->execute();
 
         return $this;
@@ -110,11 +115,13 @@ class Model_Student extends Model
      * @return $this;
      */
     public function returnFromAcademicLeave($group) {
-        $sql = "CALL `ControlStudentGroup`(:id, :group, false);";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `ControlStudentGroup`(:id, :group, false, :semesterID);";
 
         DB::query(Database::SELECT, $sql)
             ->param(':id', $this->id)
             ->param(':group', (int) $group)
+            ->param(':semesterID', $semesterID)
             ->execute();
 
         return $this;
diff --git a/~dev_rating/application/classes/Model/Students.php b/~dev_rating/application/classes/Model/Students.php
index 421338866b33e3c2d870353d3bb6412c4c4104ef..eac86847e0f99dcc0949ff466cabe44818979094 100644
--- a/~dev_rating/application/classes/Model/Students.php
+++ b/~dev_rating/application/classes/Model/Students.php
@@ -3,7 +3,8 @@
 class Model_Students extends Model
 {
     public static function ofDiscipline($id) {
-        $sql = "CALL `GetStudentsForDiscipline`('$id'); ";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetStudentsForDiscipline`('$id', $semesterID); ";
         return DB::query(Database::SELECT, $sql)->execute();
     }
 
@@ -12,7 +13,8 @@ class Model_Students extends Model
      * @return Database_Result
      */
     public static function ofGroup($group) {
-        $sql = "CALL `GetStudents`('$group'); ";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetStudents`('$group', $semesterID); ";
         return DB::query(Database::SELECT, $sql)->execute();
     }
 
@@ -27,14 +29,16 @@ class Model_Students extends Model
     }
 
     public static function byFaculty($facultyID, $gradeID, $groupID) {
-        $sql = "CALL `GetStudentsByFaculty`('$facultyID', '$gradeID', $groupID); ";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetStudentsByFaculty`('$facultyID', '$gradeID', $groupID, $semesterID); ";
         $students = DB::query(Database::SELECT, $sql)->execute();
         return self::collect($students);
     }
 
     public static function searchStudents($GradeID, $GroupID, $FacultyID, $Name, $DisciplineID) {
         $Name = Database::instance()->escape($Name);
-        $sql = "CALL `SearchStudents`('$GradeID', '$GroupID', '$FacultyID', $Name, '$DisciplineID'); ";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `SearchStudents`('$GradeID', '$GroupID', '$FacultyID', $Name, '$DisciplineID', $semesterID); ";
         return DB::query(Database::SELECT, $sql)->execute();
     }
 
diff --git a/~dev_rating/application/classes/Model/Teacher.php b/~dev_rating/application/classes/Model/Teacher.php
index 1fa742c4aebe83e76f26e178743727ff51e7fd85..6676691d38cb17a96c51ba621c8e5af2f0a5fb1e 100644
--- a/~dev_rating/application/classes/Model/Teacher.php
+++ b/~dev_rating/application/classes/Model/Teacher.php
@@ -16,8 +16,10 @@ class Model_Teacher extends Model
 
     /** @return Model_Discipline[] */
     public function getDisciplines() {
-        $sql = "CALL `GetDisciplinesForTeacher`(:id); ";
+        $semesterID = User::instance()->SemesterID;
+        $sql = "CALL `GetDisciplinesForTeacher`(:id, :semesterID); ";
         $query = DB::query(Database::SELECT, $sql)
+            ->param(':semesterID', $semesterID)
             ->param(':id', $this->ID)
             ->execute();
 
diff --git a/~dev_rating/modules/account/classes/Kohana/User.php b/~dev_rating/modules/account/classes/Kohana/User.php
index 399673809fc5d269f8ff75ac95a1a447dfc15d33..9bafaa44f3d60e89370f4ac371f4271a6658b382 100644
--- a/~dev_rating/modules/account/classes/Kohana/User.php
+++ b/~dev_rating/modules/account/classes/Kohana/User.php
@@ -82,10 +82,7 @@ class Kohana_User implements ArrayAccess
     }
 
     public function SetSemester($semesterID) {
-        $res = $this->_model->SetSemesterID($semesterID);
-        if ($res >= 0) {
-            $this->_session->set("SemesterID", "$semesterID");
-        }
+        $this->_session->set("SemesterID", "$semesterID");
     }
 
 
diff --git a/~dev_rating/modules/account/classes/Model/Kohana/Account.php b/~dev_rating/modules/account/classes/Model/Kohana/Account.php
index b886486a18b0b8dec5f4c56be256f12cccc53d8c..a76778ca07dd530ce56e9310d00afb8fb18df03e 100644
--- a/~dev_rating/modules/account/classes/Model/Kohana/Account.php
+++ b/~dev_rating/modules/account/classes/Model/Kohana/Account.php
@@ -66,6 +66,10 @@ class Model_Kohana_Account extends Model
 
     public function createTeacherByDepName($lastName, $firstName, $secondName, $departmentID, $facultyID, $activationCode)
     {
+        if ($departmentID == '') {
+            return -1;
+        }
+
         $db = Database::instance();
         $lastName = $db->escape($lastName);
         $secondName = $db->escape($secondName);
@@ -115,7 +119,8 @@ class Model_Kohana_Account extends Model
 
     public static function getPersonalInfo($id)
     {
-        $sql = "CALL `GetPersonalInfo`('$id');";
+        $semesterID = User::instance()->offsetGet('SemesterID');
+        $sql = "CALL `GetPersonalInfo`('$id', $semesterID);";
         $query = DB::query(Database::SELECT, $sql)->execute();
         return $query[0];
     }
@@ -130,7 +135,7 @@ class Model_Kohana_Account extends Model
     public function changeMail($id, $mail)
     {
         $mail = Database::instance()->escape($mail);
-        $sql = "SELECT `ChangeMail`('$id', $mail) AS Num;";
+        $sql = "SELECT `ChangeAccountData`('$id', $mail, 'email') AS Num;";
         $query = DB::query(Database::SELECT, $sql)->execute();
         return $query->get('Num');
     }
@@ -138,7 +143,7 @@ class Model_Kohana_Account extends Model
     public function changeLogin($id, $login)
     {
         $login = Database::instance()->escape($login);
-        $sql = "SELECT `ChangeLogin`('$id', $login) AS Num;";
+        $sql = "SELECT `ChangeAccountData`('$id', $login, 'login') AS Num;";
         $query = DB::query(Database::SELECT, $sql)->execute();
         return $query->get('Num');
     }
@@ -146,7 +151,7 @@ class Model_Kohana_Account extends Model
     public function changePassword($id, $password)
     {
         $password = Database::instance()->escape($password);
-        $sql = "SELECT `ChangePassword`('$id', $password) AS Num;";
+        $sql = "SELECT `ChangeAccountData`('$id', $password, 'password') AS Num;";
         $query = DB::query(Database::SELECT, $sql)->execute();
         return $query->get('Num');
     }
@@ -154,7 +159,7 @@ class Model_Kohana_Account extends Model
     public function getAccNumByLogin($login)
     {
         $login = Database::instance()->escape($login);
-        $sql = "SELECT `GetAccCountByLogin`($login) AS Num;";
+        $sql = "SELECT `CheckAccountExistence`($login, 'login') AS Num;";
         $res = DB::query(Database::SELECT, $sql)->execute();
         return $res->get('Num');
     }
@@ -162,7 +167,7 @@ class Model_Kohana_Account extends Model
     public function getAccNumByMail($email)
     {
         $email = Database::instance()->escape($email);
-        $sql = "SELECT `GetAccCountByMail`($email) AS Num;";
+        $sql = "SELECT `CheckAccountExistence`($email, 'email') AS Num;";
         $res = DB::query(Database::SELECT, $sql)->execute();
         return $res->get('Num');
     }
@@ -170,7 +175,7 @@ class Model_Kohana_Account extends Model
     public function isActivationCodeValid($code)
     {
         $code = Database::instance()->escape($code);
-        $sql = "SELECT `GetAccCountByCode`($code) AS Num;";
+        $sql = "SELECT `CheckAccountExistence`($code, 'code') AS Num;";
         $res = DB::query(Database::SELECT, $sql)->execute();
 
         $count = $res[0]['Num'];
@@ -237,15 +242,4 @@ class Model_Kohana_Account extends Model
         return $id;
     }
 
-    public function SetSemesterID($semesterID)
-    {
-        $sql = "SELECT `SetSemesterID`('$semesterID') AS `Num`; ";
-        $res = DB::query(Database::SELECT, $sql)->execute();
-
-        $id = 0;
-        foreach ($res as $value) {
-            $id = $value['Num'];
-        }
-        return $id;
-    }
 }
\ No newline at end of file