diff --git a/db/StoredFunctions.sql b/db/StoredFunctions.sql
index 5ddbab2f252085b1c2256da82eed09d6cd0f78e9..a9720982187be8447b4c37ee0e9cff4aeaa228ca 100644
--- a/db/StoredFunctions.sql
+++ b/db/StoredFunctions.sql
@@ -18,6 +18,14 @@ 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//
+
 
 # -------------------------------------------------------------------------------------------
 # Label: abbreviations
@@ -34,90 +42,116 @@ 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 INT DEFAULT -1;
+
+    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 ( vAttachType != 2 ); # NULL or vAttachType != detach
 END //
 
 
 # check, that teacher teach this course
 drop function if exists InternalIsTeacherBounded//
-CREATE FUNCTION `InternalIsTeacherBounded`
-    (   `pTeacherID` INT, `pDisciplineID` INT) RETURNS BOOLEAN
+CREATE FUNCTION `InternalIsTeacherBounded` (
+        `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
+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);
+    DECLARE vAuthorID INT DEFAULT -1;
+
+    SELECT disciplines.AuthorID INTO vAuthorID
+        FROM `disciplines`
+        WHERE disciplines.ID = pDisciplineID
+        LIMIT 1;
+
+    RETURN ( vAuthorID = pTeacherID );
 END //
 
 
 DROP FUNCTION IF EXISTS GetRateForDisc//
-CREATE FUNCTION `GetRateForDisc`
-    (   `pStudentID` INT, `pDisciplineID` INT) RETURNS int(11)
+CREATE FUNCTION `GetRateForDisc` (
+        `pStudentID` INT,
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
-    DECLARE vRate INT DEFAULT -1;
+    DECLARE vRate, vExamRate INT DEFAULT 0;
 
-    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
-                    )
-            )
+    # TODO: into temp table
+
+    # get last exam rate
+    SELECT submodules.ID INTO vExamRate
+        FROM view_roadmap
+        INNER JOIN `rating_table` ON rating_table.SubmoduleID = view_roadmap.SubmoduleID AND
+                                     rating_table.StudentID = pStudentID
+        WHERE   view_roadmap.DisciplineID = pDisciplineID AND
+                view_roadmap.ModuleType = 'exam'
+        ORDER BY submodules.OrderNum DESC
         LIMIT 1;
 
-    RETURN  vRate;
+    # regular + extra + bonus rate
+    SELECT SUM(rating_table.Rate) INTO vRate
+        FROM view_roadmap
+        INNER JOIN `rating_table` ON rating_table.SubmoduleID = view_roadmap.SubmoduleID AND
+                                     rating_table.StudentID = pStudentID
+        WHERE   view_roadmap.DisciplineID = pDisciplineID AND
+                view_roadmap.ModuleType != 'exam';
+
+    RETURN vRate + vExamRate;
 END //
 
 
 DROP FUNCTION IF EXISTS SetExamPeriodOption//
-CREATE FUNCTION `SetExamPeriodOption`
-    (   `pStudentID` INT, `pSubmoduleID` INT,
+CREATE FUNCTION `SetExamPeriodOption` (
+        `pStudentID` INT,
+        `pSubmoduleID` INT,
         `pType` VARCHAR(30) CHARSET utf8 # enum('absence','pass')
     ) RETURNS int(11)
     NO SQL
@@ -135,21 +169,26 @@ END //
 
 # check, if any module is created
 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 +197,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,8 +214,10 @@ 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
@@ -185,14 +226,16 @@ BEGIN
         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`
@@ -205,13 +248,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 //
 
 
@@ -237,8 +286,8 @@ END //
 # -------------------------------------------------------------------------------------------
 
 DROP FUNCTION IF EXISTS CreateFaculty //
-CREATE FUNCTION CreateFaculty
-    (   `pFacultyName` VARCHAR(100) CHARSET utf8,
+CREATE FUNCTION CreateFaculty (
+        `pFacultyName` VARCHAR(100) CHARSET utf8,
         `pFacultyAbbr` VARCHAR(20) CHARSET utf8
     ) RETURNS INT(11)
     NO SQL
@@ -246,8 +295,7 @@ BEGIN
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
     INSERT INTO faculties
-    (Name, Abbr)
-    VALUES(pFacultyName, pFacultyAbbr);
+        (Name, Abbr) VALUES(pFacultyName, pFacultyAbbr);
     RETURN 0;
 END //
 
@@ -256,28 +304,23 @@ END //
 # -------------------------------------------------------------------------------------------
 
 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;
 
-        SELECT faculties.ID INTO vChecker
-        FROM `faculties`
-        WHERE faculties.ID = pFacultyID
-        LIMIT 1;
+    INSERT INTO departments
+        (Name, FacultyID) VALUES(pName, pFacultyID);
 
-        IF vChecker > 0 THEN
-            INSERT INTO departments
-            (Name, FacultyID)
-            VALUES(pName, pFacultyID);
-            RETURN 0;
-        END IF;
+    IF ROW_COUNT() = 0 THEN
         RETURN -1;
-    END //
+    ELSE
+        RETURN LAST_INSERT_ID();
+    END IF;
+END //
 
 # -------------------------------------------------------------------------------------------
 # Label: study groups
@@ -285,10 +328,12 @@ NO SQL
 
 # 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)
     NO SQL
 BEGIN
     # check GradeID, SpecID constraints and (GradeID, GroupNum, SpecID) - unique
@@ -302,13 +347,35 @@ BEGIN
 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,
+CREATE FUNCTION `CreateSubject` (
+        `pFacultyID` INT,
         `pSubjectName` VARCHAR(200) CHARSET utf8,
         `pSubjectAbbr` VARCHAR(20) CHARSET utf8
     )   RETURNS int(11)
@@ -316,34 +383,32 @@ CREATE FUNCTION `CreateSubject`
 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)
             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 TEXT
     NO SQL
 BEGIN
     DECLARE vChecker INT DEFAULT -1;
@@ -359,7 +424,7 @@ BEGIN
 
     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 int(11)
     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,60 @@ 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
     END IF;
     RETURN @vAccountID;
 END //
 
 
-
-DROP FUNCTION IF EXISTS ChangePassword//
-CREATE FUNCTION `ChangePassword`
-    (   `pUserID` INT, `pPassword` VARCHAR(255) CHARSET utf8
-    )   RETURNS int(11)
-    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)
+DROP FUNCTION IF EXISTS ChangeAccountData//
+CREATE FUNCTION `ChangeAccountData` (
+        `pUserID` INT,
+        `pData` TEXT CHARSET utf8,
+        `pType` enum('login', 'email', 'password')
+    ) RETURNS int(11) # 0 - success
     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 +544,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 +558,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,14 +579,14 @@ 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,
@@ -558,14 +598,15 @@ 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 +614,36 @@ 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;
-    END IF;
-
-    # try to find a department with pDepartmentName
-    SELECT departments.ID
-        INTO vDepID
+    # try to find a department with same name \pDepartmentName
+    SELECT departments.ID INTO vDepID
         FROM `departments`
-        WHERE   (departments.Name = pDepartmentName AND departments.FacultyID = pFacultyID)
+        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
+        SET vDepID = CreateDepartment(pDepartmentName, pFacultyID);
+        IF vDepID < 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,10 +651,10 @@ 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;
@@ -635,7 +662,8 @@ BEGIN
     SELECT disciplines_teachers.ID INTO vDiscTeacherID
         FROM `disciplines_teachers`
         WHERE disciplines_teachers.DisciplineID = pDisciplineID AND
-              disciplines_teachers.TeacherID = pTeacherID;
+              disciplines_teachers.TeacherID = pTeacherID
+        LIMIT 1;
 
     IF vDiscTeacherID > 0 THEN
         RETURN 1;
@@ -658,12 +686,16 @@ END //
 # Label: students
 # -------------------------------------------------------------------------------------------
 
+# TODO: magic constants (UserRoleID)
+# TODO: transaction
 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 +703,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,17 +719,20 @@ BEGIN
     INSERT INTO `students`
         (AccountID, LastName, FirstName, SecondName)
         VALUES  (vAccountID, pLastName, pFirstName, pSecondName);
+    SET vStudentID = LAST_INSERT_ID();
 
+#     SELECT general_settings.Val INTO vSemesterID
+#         FROM `general_settings`
+#         WHERE general_settings.Name = 'SemesterID'
+#         LIMIT 1;
 
-    SELECT general_settings.Val INTO vSemesterID
-        FROM `general_settings`
-        WHERE general_settings.Name = 'SemesterID'
-        LIMIT 1;
+    # TODO: add param semester id\ instead @currentSemesterID
+    RETURN ControlStudentGroup(vStudentID, vGroupID, FALSE);
 
     # bind group in current semester
     INSERT INTO `students_groups`
         (StudentID, GroupID, SemesterID)
-        VALUES (LAST_INSERT_ID(), vGroupID, vSemesterID);
+        VALUES (vStudentID, vGroupID, vSemesterID);
 
     RETURN 0;
 END //
@@ -710,8 +740,8 @@ 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,
@@ -726,6 +756,9 @@ BEGIN
     DECLARE vAccountID, vGradeID, vSpecID, vGroupID INT DEFAULT -1;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
+
+    # TODO: extract CreateGroup, CreateGrade, ...
+
     # try to find grade
     SELECT grades.ID INTO vGradeID
         FROM `grades`
@@ -794,6 +827,7 @@ BEGIN
     DECLARE vChecker INT DEFAULT 0;
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
 
+    # TODO: add semester id param
     # out to study leave
     IF pState THEN
         UPDATE `students_groups`
@@ -839,17 +873,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 +898,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 +922,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 +947,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,8 +988,9 @@ END //
 
 
 DROP FUNCTION IF EXISTS ChangeDisciplineControl//
-CREATE FUNCTION `ChangeDisciplineControl`
-    (   `pTeacherID` INT, `pDisciplineID` INT,
+CREATE FUNCTION `ChangeDisciplineControl` (
+        `pTeacherID` INT,
+        `pDisciplineID` INT,
         `pExamType` VARCHAR(30) CHARSET utf8
     )   RETURNS int(11)
     NO SQL
@@ -966,8 +1007,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 +1021,13 @@ BEGIN
         WHERE disciplines.ID = pDisciplineID
         LIMIT 1;
 
-    # this magic check that type change between exam <-> credit/grading_credit
+    # check type changing: exam <-> credit/grading_credit
     IF vOldExamType = 1 XOR pExamType != 'exam' THEN # 1 - exam
         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 +1035,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 +1047,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 +1059,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 +1095,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 +1122,7 @@ BEGIN
         RETURN 1;
     END IF;
 
+    # TODO: add param SemesterID
     SELECT disciplines.SemesterID INTO vSemesterID
         FROM `disciplines`
         WHERE disciplines.ID = pDisciplineID
@@ -1083,12 +1130,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,8 +1148,10 @@ 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
@@ -1115,6 +1164,7 @@ BEGIN
         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
@@ -1146,9 +1196,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 +1211,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,19 +1224,22 @@ 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
@@ -1194,6 +1249,9 @@ BEGIN
         RETURN -1;
     END IF;
 
+    # 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`
@@ -1220,8 +1278,10 @@ END //
 
 
 DROP FUNCTION IF EXISTS BindTeacher//
-CREATE FUNCTION `BindTeacher`
-    (`pAuthorTeacherID` INT, `pBindingTeacherID` INT, `pDisciplineID` INT
+CREATE FUNCTION `BindTeacher` (
+        `pAuthorTeacherID` INT,
+        `pBindingTeacherID` INT,
+        `pDisciplineID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -1235,15 +1295,17 @@ BEGIN
         (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 //
 
 
 
 DROP FUNCTION IF EXISTS UnbindTeacher//
-CREATE FUNCTION `UnbindTeacher`
-    (   `pAuthorTeacherID` INT, `pBindingTeacher` INT, `pDisciplineID` INT
+CREATE FUNCTION `UnbindTeacher` (
+        `pAuthorTeacherID` INT,
+        `pBindingTeacher` INT,
+        `pDisciplineID` INT
     ) RETURNS int(11)
     NO SQL
 BEGIN
@@ -1262,9 +1324,11 @@ END //
 
 # assign new author to discipline
 DROP FUNCTION IF EXISTS DelegateDiscipline//
-CREATE FUNCTION `DelegateDiscipline`
-    (   `pAuthorTeacherID` INT, `pNewAuthorID` INT, `pDisciplineID` INT
-    )   RETURNS int(11)
+CREATE FUNCTION `DelegateDiscipline` (
+        `pAuthorTeacherID` INT,
+        `pNewAuthorID` INT,
+        `pDisciplineID` INT
+    ) RETURNS int(11)
     NO SQL
 BEGIN
     DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
@@ -1286,9 +1350,10 @@ 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
@@ -1323,17 +1388,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;
 
@@ -1358,8 +1423,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;
@@ -1378,9 +1443,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`
@@ -1393,18 +1460,19 @@ 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
+    ) 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 = @CurrentSemesterID AND
+                ( disciplines.ExamType = 'credit' OR disciplines.ExamType = 'grading_credit');
     RETURN 0;
 END //
 
@@ -1416,10 +1484,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`
@@ -1434,8 +1503,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
@@ -1467,9 +1537,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;
@@ -1479,6 +1550,7 @@ BEGIN
         RETURN -1;
     END IF;
 
+    # TODO: exists
     # check exam module existence
     SELECT modules.ID
         INTO vChecker
@@ -1503,8 +1575,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
@@ -1558,9 +1631,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;
@@ -1599,9 +1673,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;
@@ -1633,9 +1708,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,
@@ -1688,9 +1765,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;
@@ -1720,8 +1798,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
@@ -1760,12 +1839,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;
@@ -1798,11 +1877,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;
@@ -1828,11 +1907,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;
@@ -1859,8 +1938,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
@@ -1897,12 +1977,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;
@@ -1946,8 +2028,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,
@@ -2004,8 +2089,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;
@@ -2024,8 +2110,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;
@@ -2059,8 +2147,8 @@ END //
 
 
 DROP FUNCTION IF EXISTS SetStudentRate//
-CREATE FUNCTION `SetStudentRate`
-    (   `pTeacherID` INT,
+CREATE FUNCTION `SetStudentRate` (
+        `pTeacherID` INT,
         `pStudentID` INT,
         `pSubmoduleID` INT,
         `pRate` INT
@@ -2093,7 +2181,7 @@ 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
+    IF  NOT InternalIsStudentAttached(pStudentID, vDisciplineID, @CurrentSemesterID) OR
         NOT InternalIsTeacherBounded(pTeacherID, vDisciplineID) OR
         pRate > vMaxRate OR
         (vIsOver AND (vModuleType = 1 OR vModuleType = 3)) # 1 - regular, 3 - bonus
@@ -2146,8 +2234,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
@@ -2185,10 +2274,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;
@@ -2224,8 +2313,9 @@ 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;
@@ -2253,8 +2343,9 @@ BEGIN
 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;
@@ -2268,7 +2359,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/~dev_rating/modules/account/classes/Model/Kohana/Account.php b/~dev_rating/modules/account/classes/Model/Kohana/Account.php
index b886486a18b0b8dec5f4c56be256f12cccc53d8c..2653b0987b8621ce5a92635699aea99bda3d4994 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);
@@ -130,7 +134,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 +142,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 +150,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 +158,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 +166,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 +174,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'];