Skip to content
Snippets Groups Projects
functions.sql 68.3 KiB
Newer Older
PavelBegunkov's avatar
PavelBegunkov committed
            SET vChecker = InternalIsMapCreated(pDisciplineID);
PavelBegunkov's avatar
PavelBegunkov committed
            IF vChecker >= 61 THEN # can't add exam module ( > 100 points)
                RETURN 1;
            END IF;
            SET vChecker = AddModuleExam(pTeacherID, pDisciplineID);

            # delete extra submodules(only 1 extra for exam)
            DELETE FROM `submodules`
                WHERE submodules.OrderNum > 1 AND submodules.ModuleID = vExtraID;
PavelBegunkov's avatar
PavelBegunkov committed

            SET vExtraMax = 7;
PavelBegunkov's avatar
PavelBegunkov committed
        ELSE # change to credit
            SET vExtraMax = 29;
            SET vChecker = DeleteModuleExam(pTeacherID, pDisciplineID);
            # 2 extra submodules (1 already created for exam)
            SET vChecker = AddSubmodule(pTeacherID, vExtraID, vExtraMax, '', NULL, 'LandmarkControl');
        END IF;
    END IF;

    # set new exam type
    UPDATE `disciplines`
        SET disciplines.ExamType = pExamType
        WHERE disciplines.ID = pDisciplineID
        LIMIT 1;

    # set max rate for extra
PavelBegunkov's avatar
PavelBegunkov committed
    UPDATE `submodules`
        SET submodules.MaxRate = vExtraMax
        WHERE submodules.ModuleID = vExtraID;
    RETURN 0;
END //

DROP FUNCTION IF EXISTS ChangeDisciplineHours//
CREATE FUNCTION `ChangeDisciplineHours` (
PavelBegunkov's avatar
PavelBegunkov committed
    `pTeacherID` INT,
    `pDisciplineID` INT,
    `pHours` INT,
    `pType` INT
    # Type: 0 - Practice Hours, 1 - Lecture Hours, 2 - Lab Hours
)   RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    IF NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) THEN
        RETURN -1;
    END IF;

    CASE pType
    WHEN 0 THEN
        UPDATE `disciplines`
            SET disciplines.PracticeCount = pHours
            WHERE disciplines.ID = pDisciplineID
            LIMIT 1;
    WHEN 1 THEN
        UPDATE `disciplines`
            SET disciplines.LectureCount = pHours
            WHERE disciplines.ID = pDisciplineID
            LIMIT 1;
    WHEN 2 THEN
        UPDATE `disciplines`
            SET disciplines.LabCount = pHours
            WHERE disciplines.ID = pDisciplineID
            LIMIT 1;
    END CASE;
    RETURN ROW_COUNT()-1;
END //

DROP FUNCTION IF EXISTS LogBind//
CREATE FUNCTION `LogBind` (
    `pDisciplineID` INT,
    `pTeacherID` INT,
    `EntityID` INT,
    `pAttach` enum('attach', 'detach'),
    `pType` enum('group', 'student')
) RETURNS int(11) # 0 - success, < 0 - failed
NO SQL
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
    IF pType = 'group' THEN
        INSERT INTO `logs_binds_groups`
            (`DisciplineID`, `TeacherID`, `GroupID`, `Type`)
            VALUES (pDisciplineID, pTeacherID, EntityID, pAttach);
    ELSEIF pType = 'student' THEN
        INSERT INTO `logs_binds_students`
            (`DisciplineID`, `TeacherID`, `StudentID`, `Type`)
            VALUES (pDisciplineID, pTeacherID, EntityID, pAttach);
    END IF;
    RETURN ROW_COUNT()-1;
END //
PavelBegunkov's avatar
PavelBegunkov committed

DROP FUNCTION IF EXISTS BindGroup//
CREATE FUNCTION `BindGroup` (
        `pTeacherID` INT,
        `pDisciplineID` INT,
        `pGroupID` INT
PavelBegunkov's avatar
PavelBegunkov committed
    ) RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vSemesterID INT DEFAULT -1;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -3;
    SET @isAttached := -1;

    # todo: move to php layer
    IF  NOT InternalIsTeacherBound(pTeacherID, pDisciplineID) OR
PavelBegunkov's avatar
PavelBegunkov committed
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    # bind whole group
PavelBegunkov's avatar
PavelBegunkov committed
    INSERT INTO `disciplines_groups`
        (DisciplineID, GroupID)
        VALUES ( pDisciplineID, pGroupID )
        ON DUPLICATE KEY UPDATE
            disciplines_groups.ID = ( @isAttached := LAST_INSERT_ID(disciplines_groups.ID) );

PavelBegunkov's avatar
PavelBegunkov committed
    IF @isAttached > 0 THEN # group was attached
PavelBegunkov's avatar
PavelBegunkov committed
        SET vSemesterID = GetDisciplineProperty(pDisciplineID, 'semester');
        # delete students of this group which were bound to discipline before
PavelBegunkov's avatar
PavelBegunkov committed
        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
                );
        RETURN 1;
    RETURN LogBind(pDisciplineID, pTeacherID, pGroupID, 'attach', 'group');
PavelBegunkov's avatar
PavelBegunkov committed
END //



DROP FUNCTION IF EXISTS BindStudent//
CREATE FUNCTION `BindStudent` (
        `pTeacherID` INT,
        `pDisciplineID` INT,
        `pStudentID` INT
PavelBegunkov's avatar
PavelBegunkov committed
    )   RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vChecker, vStudentGroupID, vTemp, vSemesterID INT DEFAULT -1;
    DECLARE vInGroup BOOLEAN DEFAULT FALSE;
PavelBegunkov's avatar
PavelBegunkov committed
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;

    # todo: move to php layer
    IF NOT InternalIsTeacherBound(pTeacherID, pDisciplineID) THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

PavelBegunkov's avatar
PavelBegunkov committed
    SET vSemesterID = GetDisciplineProperty(pDisciplineID, 'semester');
    SET vStudentGroupID = GetStudentGroup(pStudentID, vSemesterID);

    # check if student's group is bound yet
        SELECT * FROM `disciplines_groups`
            WHERE disciplines_groups.DisciplineID = pDisciplineID AND
                  disciplines_groups.GroupID = vStudentGroupID
    IF vInGroup THEN # student in group -> try to remove detached attribute
PavelBegunkov's avatar
PavelBegunkov committed
        DELETE FROM `disciplines_students`
            WHERE   disciplines_students.DisciplineID = pDisciplineID AND
                    disciplines_students.StudentID = pStudentID
PavelBegunkov's avatar
PavelBegunkov committed
            LIMIT 1;
    ELSE # bind stand alone student ;(
        INSERT INTO `disciplines_students`
            (DisciplineID, StudentID, Type)
            VALUES (pDisciplineID, pStudentID, 'attach')
            ON DUPLICATE KEY UPDATE
                disciplines_students.Type = 'attach';
PavelBegunkov's avatar
PavelBegunkov committed
    END IF;

    RETURN LogBind(pDisciplineID, pTeacherID, pStudentID, 'attach', 'student');
PavelBegunkov's avatar
PavelBegunkov committed
END //



DROP FUNCTION IF EXISTS UnbindGroup//
CREATE FUNCTION `UnbindGroup` (
        `pTeacherID` INT,
        `pDisciplineID` INT,
        `pGroupID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vSemesterID INT DEFAULT -1;

    # todo: move to php layer
    IF NOT InternalIsTeacherBound(pTeacherID, pDisciplineID) OR InternalIsMapLocked(pDisciplineID) THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

    # detach group from the discipline
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `disciplines_groups`
        WHERE   disciplines_groups.DisciplineID = pDisciplineID AND
                disciplines_groups.GroupID = pGroupID
        LIMIT 1;
PavelBegunkov's avatar
PavelBegunkov committed
    SET vSemesterID = GetDisciplineProperty(pDisciplineID, 'semester');
PavelBegunkov's avatar
PavelBegunkov committed
    # 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
          );

    RETURN LogBind(pDisciplineID, pTeacherID, pGroupID, 'detach', 'group');
PavelBegunkov's avatar
PavelBegunkov committed
END //



DROP FUNCTION IF EXISTS UnbindStudent//
CREATE FUNCTION `UnbindStudent` (
        `pTeacherID` INT,
        `pDisciplineID` INT,
        `pStudentID` INT
PavelBegunkov's avatar
PavelBegunkov committed
    ) RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vInGroup, vStudentGroupID, vSemesterID INT DEFAULT -1;
PavelBegunkov's avatar
PavelBegunkov committed
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
    # todo: move to php layer
    IF  NOT InternalIsTeacherBound(pTeacherID, pDisciplineID) THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

PavelBegunkov's avatar
PavelBegunkov committed
    SET vSemesterID = GetDisciplineProperty(pDisciplineID, 'semester');
    SET vStudentGroupID = GetStudentGroup(pStudentID, vSemesterID);
    # 2. check if student's group is bound yet
    SET vInGroup = EXISTS(
        SELECT * FROM `disciplines_groups`
        WHERE disciplines_groups.DisciplineID = pDisciplineID AND
              disciplines_groups.GroupID = vStudentGroupID
        LIMIT 1
    );
    IF vInGroup > 0 THEN # student in general group
PavelBegunkov's avatar
PavelBegunkov committed
        INSERT INTO `disciplines_students`
            (DisciplineID, StudentID, Type)
            VALUES (pDisciplineID, pStudentID, 'detach')
                ON DUPLICATE KEY UPDATE disciplines_students.Type='detach';
PavelBegunkov's avatar
PavelBegunkov committed
    ELSE
        DELETE FROM `disciplines_students`
            WHERE   disciplines_students.DisciplineID = pDisciplineID AND
                    disciplines_students.StudentID = pStudentID
            LIMIT 1;
PavelBegunkov's avatar
PavelBegunkov committed
    END IF;
    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    RETURN LogBind(pDisciplineID, pTeacherID, pStudentID, 'detach', 'student');
DROP FUNCTION IF EXISTS Discipline_BindTeacher//
CREATE FUNCTION `Discipline_BindTeacher` (
    `pDisciplineID` INT,
    `pBindingTeacherID` INT
) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
PavelBegunkov's avatar
PavelBegunkov committed
    # try to insert BindingTeacher in access list
    INSERT INTO `disciplines_teachers`
        (DisciplineID, TeacherID)
        VALUES (pDisciplineID, pBindingTeacherID)
        ON DUPLICATE KEY UPDATE # just stub
            disciplines_teachers.ID = LAST_INSERT_ID(disciplines_teachers.ID);
PavelBegunkov's avatar
PavelBegunkov committed
    RETURN 0;
END //



DROP FUNCTION IF EXISTS UnbindTeacher//
DROP FUNCTION IF EXISTS Discipline_UnbindTeacher//
CREATE FUNCTION `Discipline_UnbindTeacher` (
    `pDisciplineID` INT,
    `pBindingTeacher` INT
) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DELETE FROM `disciplines_teachers`
        WHERE   disciplines_teachers.DisciplineID = pDisciplineID AND
                disciplines_teachers.TeacherID = pBindingTeacher
        LIMIT 1;
    RETURN ROW_COUNT()-1;
# assign new author to discipline
PavelBegunkov's avatar
PavelBegunkov committed
DROP FUNCTION IF EXISTS DelegateDiscipline//
DROP FUNCTION IF EXISTS Discipline_Delegate//
CREATE FUNCTION `Discipline_Delegate` (
    `pDisciplineID` INT,
    `pNewAuthorID` INT
) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vTemp INT DEFAULT 0;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;

    SET vTemp = Discipline_BindTeacher(pDisciplineID, pNewAuthorID);
PavelBegunkov's avatar
PavelBegunkov committed

    UPDATE `disciplines`
        SET disciplines.AuthorID = pNewAuthorID
        WHERE disciplines.ID = pDisciplineID
        LIMIT 1;
    RETURN ROW_COUNT()-1;
END //


PavelBegunkov's avatar
PavelBegunkov committed
# erase all discipline's rates(and logs), unlock discipline for editing
PavelBegunkov's avatar
PavelBegunkov committed
DROP FUNCTION IF EXISTS ClearDiscipline//
CREATE FUNCTION `ClearDiscipline` (
        `pAuthorTeacherID` INT,
        `pDisciplineID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
PavelBegunkov's avatar
PavelBegunkov committed
    IF NOT InternalIsTeacherAuthor(pAuthorTeacherID, pDisciplineID) THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

    # clear logs
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `logs_rating`
PavelBegunkov's avatar
PavelBegunkov committed
        WHERE logs_rating.SubmoduleID IN
PavelBegunkov's avatar
PavelBegunkov committed
            (SELECT view_roadmap.SubmoduleID
                FROM `view_roadmap`
                WHERE view_roadmap.DisciplineID = pDisciplineID);

    # clear rating
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `rating_table`
PavelBegunkov's avatar
PavelBegunkov committed
        WHERE rating_table.SubmoduleID IN
PavelBegunkov's avatar
PavelBegunkov committed
            (SELECT view_roadmap.SubmoduleID
             FROM `view_roadmap`
             WHERE view_roadmap.DisciplineID = pDisciplineID);

    # unlock discipline
PavelBegunkov's avatar
PavelBegunkov committed
    UPDATE `disciplines`
xamgore's avatar
xamgore committed
        SET disciplines.IsLocked = 0
PavelBegunkov's avatar
PavelBegunkov committed
        WHERE disciplines.ID = pDisciplineID
        LIMIT 1;

    RETURN ROW_COUNT()-1;
END //



DROP FUNCTION IF EXISTS DeleteDiscipline//
DROP FUNCTION IF EXISTS Discipline_Delete//
CREATE FUNCTION `Discipline_Delete` (
        `pDisciplineID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    # delete roadmap
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `submodules`
        WHERE submodules.ModuleID IN (
            SELECT modules.ID
PavelBegunkov's avatar
PavelBegunkov committed
                FROM `modules`
                WHERE modules.DisciplineID = pDisciplineID
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `modules`
        WHERE modules.DisciplineID = pDisciplineID;

    # detach all entities from discipline
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `disciplines_teachers`
        WHERE disciplines_teachers.DisciplineID = pDisciplineID;
    DELETE FROM `disciplines_students`
        WHERE disciplines_students.DisciplineID = pDisciplineID;
    DELETE FROM `disciplines_groups`
        WHERE disciplines_groups.DisciplineID = pDisciplineID;
    DELETE FROM logs_binds_groups
        WHERE logs_binds_groups.DisciplineID = pDisciplineID;
    DELETE FROM logs_binds_students
        WHERE logs_binds_students.DisciplineID = pDisciplineID;

    # delete discipline
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `disciplines`
        WHERE disciplines.ID = pDisciplineID
        LIMIT 1;

    RETURN 0;
END //


# get count of related with discipline records in rating_table
DROP FUNCTION IF EXISTS Discipline_CountRatings//
CREATE FUNCTION `Discipline_CountRatings` (
        `pDisciplineID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vRes INT DEFAULT 0;

    SELECT COUNT(rating_table.StudentID) INTO vRes
        FROM `view_roadmap`
        LEFT JOIN `rating_table` ON rating_table.SubmoduleID = view_roadmap.SubmoduleID
        WHERE view_roadmap.DisciplineID = pDisciplineID;
PavelBegunkov's avatar
PavelBegunkov committed

    RETURN vRes;
END //



DROP FUNCTION IF EXISTS RestrictAfterMilestone//
CREATE FUNCTION `RestrictAfterMilestone` (
        `pDisciplineID` INT,
        `pMilestone` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    UPDATE `disciplines`
        SET disciplines.MilestoneDate = CURDATE(),
PavelBegunkov's avatar
PavelBegunkov committed
            disciplines.Milestone = pMilestone
PavelBegunkov's avatar
PavelBegunkov committed
        WHERE disciplines.ID = pDisciplineID
        LIMIT 1;
    RETURN 0;
END //


DROP FUNCTION IF EXISTS RestrictAfterMilestoneForCredits//
CREATE FUNCTION `RestrictAfterMilestoneForCredits` (
        `pFacultyID` INT,
        `pMilestone` INT,
        `pSemesterID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    UPDATE `disciplines`
        SET disciplines.MilestoneDate = CURDATE(),
PavelBegunkov's avatar
PavelBegunkov committed
            disciplines.Milestone = pMilestone
PavelBegunkov's avatar
PavelBegunkov committed
        WHERE   disciplines.FacultyID= pFacultyID AND
                disciplines.SemesterID = pSemesterID AND
                ( disciplines.ExamType = 'credit' OR disciplines.ExamType = 'grading_credit');
PavelBegunkov's avatar
PavelBegunkov committed
    RETURN 0;
END //

PavelBegunkov's avatar
PavelBegunkov committed
# -------------------------------------------------------------------------------------------
# Label: modules
PavelBegunkov's avatar
PavelBegunkov committed
# Label: roadmap
PavelBegunkov's avatar
PavelBegunkov committed
# -------------------------------------------------------------------------------------------

DROP FUNCTION IF EXISTS ChangeModuleName//
CREATE FUNCTION `ChangeModuleName` (
        `pTeacherID` INT,
        `pModuleID` INT,
PavelBegunkov's avatar
PavelBegunkov committed
        `pName` VARCHAR(200) CHARSET utf8
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    UPDATE `modules`
        SET modules.Name = pName
        WHERE modules.ID = pModuleID AND
              modules.Type = 'regular' AND
              NOT InternalIsMapLocked(modules.DisciplineID)
PavelBegunkov's avatar
PavelBegunkov committed
        LIMIT 1;
    RETURN ROW_COUNT();
PavelBegunkov's avatar
PavelBegunkov committed
END //



DROP FUNCTION IF EXISTS AddModule//
CREATE FUNCTION `AddModule` (
        `pTeacherID` INT,
        `pDisciplineID` INT,
PavelBegunkov's avatar
PavelBegunkov committed
        `pName` VARCHAR(200) CHARSET utf8
    ) RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vOrderNum INT DEFAULT 0;
PavelBegunkov's avatar
PavelBegunkov committed
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;

    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -2;
PavelBegunkov's avatar
PavelBegunkov committed
    END IF;

    # get free orderNum
    SELECT MAX(modules.OrderNum)+1 INTO vOrderNum
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `modules`
        WHERE   modules.DisciplineID = pDisciplineID AND modules.Type = 'regular'
        LIMIT 1;
    IF vOrderNum IS NULL THEN # TODO: check unreachable code
        SET vOrderNum = 1;
    END IF;
PavelBegunkov's avatar
PavelBegunkov committed

    INSERT INTO `modules`
        (Name, OrderNum, DisciplineID )
        VALUES (pName, vOrderNum, pDisciplineID);
PavelBegunkov's avatar
PavelBegunkov committed
    RETURN LAST_INSERT_ID();
END //



DROP FUNCTION IF EXISTS AddModuleExam//
CREATE FUNCTION `AddModuleExam` (
        `pTeacherID` INT,
        `pDisciplineID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vModule, vChecker INT DEFAULT -1;
    DECLARE vIsExamExists BOOLEAN;
PavelBegunkov's avatar
PavelBegunkov committed
    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    SET vIsExamExists = EXISTS(
        SELECT * FROM `modules`
            WHERE   modules.DisciplineID = pDisciplineID AND
                    modules.Type = 'exam'
            LIMIT 1
    );
    IF vIsExamExists THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -2;
    END IF;

    INSERT INTO `modules`
        (Name, OrderNum, DisciplineID, Type)
        VALUES  ('Экзамен' , 3141592 , pDisciplineID, 'exam');
PavelBegunkov's avatar
PavelBegunkov committed

    SET vModule = LAST_INSERT_ID();
    # 3 attempt for pass exam
PavelBegunkov's avatar
PavelBegunkov committed
    SET vChecker = AddSubmodule(pTeacherID, vModule, 40, '', NULL, 'LandmarkControl');
    SET vChecker = AddSubmodule(pTeacherID, vModule, 40, '', NULL, 'LandmarkControl');
    SET vChecker = AddSubmodule(pTeacherID, vModule, 40, '', NULL, 'LandmarkControl');
    RETURN vModule;
END //


DROP FUNCTION IF EXISTS AddModuleExtra//
CREATE FUNCTION `AddModuleExtra` (
        `pTeacherID` INT,
        `pDisciplineID` INT
PavelBegunkov's avatar
PavelBegunkov committed
    ) RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vChecker, vModule, vType, vGap INT DEFAULT -1;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
PavelBegunkov's avatar
PavelBegunkov committed
    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    # try to find existing extra module
PavelBegunkov's avatar
PavelBegunkov committed
    SELECT modules.ID INTO vChecker
        FROM `modules`
        WHERE modules.DisciplineID = pDisciplineID AND modules.Type = 'extra'
        LIMIT 1;
    IF vChecker > 0 THEN
        RETURN -2;
    END IF;

    # add extra module
PavelBegunkov's avatar
PavelBegunkov committed
    INSERT INTO `modules`
        (Name, OrderNum, DisciplineID, Type)
        VALUES ('Добор баллов' , 2900666 , pDisciplineID, 'extra');


    # get discipline exam type
    SELECT  modules.ID, disciplines.ExamType INTO vModule, vType
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `modules`
        INNER JOIN `disciplines` ON disciplines.ID = modules.DisciplineID
        WHERE   modules.DisciplineID = pDisciplineID AND
                modules.Type = 'extra'
        LIMIT 1;
    IF vModule <= 0 THEN
        RETURN -1;
    END IF;

    # 1 extra attempt for exam and 2 for credit
PavelBegunkov's avatar
PavelBegunkov committed
    SET vGap = -1;
    IF vType = 1 THEN # exam
PavelBegunkov's avatar
PavelBegunkov committed
        SET vGap = 7;
    END IF;
PavelBegunkov's avatar
PavelBegunkov committed
    IF vType = 2 OR vType = 3 THEN # credit, grading_credit
PavelBegunkov's avatar
PavelBegunkov committed
        SET vGap = 29;
        SET vChecker = AddSubmodule(pTeacherID, vModule, vGap, '', NULL, 'LandmarkControl');
    END IF;

    SET vChecker = AddSubmodule(pTeacherID, vModule, vGap, '', NULL, 'LandmarkControl');
    RETURN vModule;
END //


DROP FUNCTION IF EXISTS DeleteModule//
CREATE FUNCTION `DeleteModule` (
        `pTeacherID` INT,
        `pModuleID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vDisciplineID INT DEFAULT -1;
    # get discipline ID
    SELECT disciplines.ID INTO vDisciplineID
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `modules`
        INNER JOIN `disciplines`    ON  modules.DisciplineID = disciplines.ID AND
                                        disciplines.AuthorID = pTeacherID
        WHERE modules.ID = pModuleID
        LIMIT 1;

    # check rights
    IF  NOT InternalIsTeacherAuthor(pTeacherID, vDisciplineID) OR
        InternalIsMapLocked(vDisciplineID)
PavelBegunkov's avatar
PavelBegunkov committed
    THEN
        RETURN -1;
    END IF;

    DELETE FROM `submodules`
        WHERE submodules.ModuleID = pModuleID;
    DELETE FROM `modules`
        WHERE modules.ID = pModuleID;

    # restore continuous ordering
PavelBegunkov's avatar
PavelBegunkov committed
    SET @counter = 0;
    UPDATE `modules`
        SET modules.OrderNum = (@counter := @counter + 1)
        WHERE   modules.DisciplineID = vDisciplineID AND
PavelBegunkov's avatar
PavelBegunkov committed
                modules.Type = 'regular'
        ORDER BY modules.OrderNum ASC;

    RETURN 0;
END //



DROP FUNCTION IF EXISTS DeleteModuleExam//
CREATE FUNCTION `DeleteModuleExam` (
        `pTeacherID` INT,
        `pDisciplineID` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vExamModuleID INT DEFAULT -1;
    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    # get exam module ID
    SELECT modules.ID INTO vExamModuleID
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `modules`
        WHERE   modules.Type = 'exam' AND
                modules.DisciplineID = pDisciplineID
        LIMIT 1;
    IF vExamModuleID <= 0 THEN
        RETURN -1;
    END IF;

    DELETE FROM `submodules`
        WHERE vExamModuleID = submodules.ModuleID;
    DELETE FROM `modules`
        WHERE vExamModuleID = modules.ID
        LIMIT 1;

    RETURN 0;
END //



DROP FUNCTION IF EXISTS SwapModuleOrder//
CREATE FUNCTION `SwapModuleOrder` (
        `pTeacherID` INT,
        `pModuleID1` INT,
        `pModuleID2` INT
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vChecker, vOrder1, vOrder2,
            vDisciplineID1, vDisciplineID2 INT DEFAULT -1;

    # get disciplineID and orderNum for 1st module(pModuleID1)
PavelBegunkov's avatar
PavelBegunkov committed
    SELECT  modules.OrderNum,
            modules.DisciplineID
        INTO vOrder1, vDisciplineID1
        FROM `modules`
        INNER JOIN `disciplines` ON disciplines.ID = modules.DisciplineID
        WHERE   disciplines.AuthorID = pTeacherID AND
                modules.ID = pModuleID1 AND
                modules.Type = 'regular'
        LIMIT 1;

    # get disciplineID and orderNum for 2st module(pModuleID2)
PavelBegunkov's avatar
PavelBegunkov committed
    SELECT  modules.OrderNum,
            modules.DisciplineID
        INTO vOrder2, vDisciplineID2
        FROM `modules`
        INNER JOIN `disciplines` ON disciplines.ID = modules.DisciplineID
        WHERE   disciplines.AuthorID = pTeacherID AND
                modules.ID = pModuleID2 AND
                modules.Type = 'regular'
        LIMIT 1;

    # check that modules belong to one discipline, check rights
PavelBegunkov's avatar
PavelBegunkov committed
    IF  vDisciplineID1 != vDisciplineID2 OR vDisciplineID1 <= 0 OR
        InternalIsMapLocked(vDisciplineID1) THEN
        RETURN -1;
    END IF;

PavelBegunkov's avatar
PavelBegunkov committed
    UPDATE `modules`
        SET modules.OrderNum = 271828
        WHERE modules.ID = pModuleID1;
    UPDATE `modules`
        SET modules.OrderNum = vOrder1
        WHERE modules.ID = pModuleID2
        LIMIT 1;
    UPDATE `modules`
        SET modules.OrderNum = vOrder2
        WHERE modules.ID = pModuleID1
        LIMIT 1;

    RETURN 0;
END //



DROP FUNCTION IF EXISTS AddModuleBonus//
CREATE FUNCTION `AddModuleBonus` (
        `pTeacherID` INT,
        `pDisciplineID` INT
    )   RETURNS INT(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vChecker, vModuleID INT DEFAULT -1;
    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    # check existing of bonus module
    SELECT modules.ID INTO vChecker
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `modules`
        WHERE   modules.DisciplineID = pDisciplineID AND
                modules.Type = 'bonus';
    IF vChecker > 0 THEN
        RETURN -2;
    END IF;

    INSERT INTO `modules`
        (Name, OrderNum, DisciplineID, Type)
        VALUES  ('Бонусные баллы' , 2141692 , pDisciplineID, 'bonus');
    SET vModuleID = LAST_INSERT_ID();
PavelBegunkov's avatar
PavelBegunkov committed
    SET vChecker = AddSubmodule(pTeacherID, vModuleID, 10, '', NULL, 'LandmarkControl');
    RETURN 0;
END //


DROP FUNCTION IF EXISTS DeleteModuleBonus//
CREATE FUNCTION `DeleteModuleBonus` (
        `pTeacherID` INT,
        `pDisciplineID` INT
PavelBegunkov's avatar
PavelBegunkov committed
    ) RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vBonusModuleID INT DEFAULT -1;
    IF  NOT InternalIsTeacherAuthor(pTeacherID, pDisciplineID) OR
        InternalIsMapLocked(pDisciplineID)
    THEN
        RETURN -1;
    END IF;

    # get bonus module ID
PavelBegunkov's avatar
PavelBegunkov committed
    -- todo: extract method
    SELECT modules.ID INTO vBonusModuleID
        FROM `modules`
        WHERE   modules.Type = 'bonus' AND
                modules.DisciplineID = pDisciplineID
        LIMIT 1;
PavelBegunkov's avatar
PavelBegunkov committed
    IF vBonusModuleID <= 0 THEN
        RETURN -1;
    END IF;

    DELETE FROM `submodules`
        WHERE vBonusModuleID = submodules.ModuleID;

    DELETE FROM `modules`
        WHERE vBonusModuleID = modules.ID
        LIMIT 1;

    RETURN 0;
END //



# -------------------------------------------------------------------------------------------
# Label: submodules
PavelBegunkov's avatar
PavelBegunkov committed
# Label: roadmap
PavelBegunkov's avatar
PavelBegunkov committed
# -------------------------------------------------------------------------------------------

DROP FUNCTION IF EXISTS ChangeSubmoduleMaxAndControl//
CREATE FUNCTION `ChangeSubmoduleMaxAndControl` (
        `pTeacherID`     INT,
        `pSubmoduleID`   INT,
        `pMaxRate`       INT,
        `pControlType`   VARCHAR(30) CHARSET utf8
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vChecker, vDisciplineID, vIsLocked, vNewDiscMaxRate, vCurRate INT DEFAULT -1;
    # check that discipline and submodule exists and doesn't locked
xamgore's avatar
xamgore committed
    SELECT  disciplines.IsLocked,
PavelBegunkov's avatar
PavelBegunkov committed
            disciplines.MaxRate - submodules.MaxRate + pMaxRate
            INTO vIsLocked, vNewDiscMaxRate
        FROM `submodules`
        INNER JOIN `modules`        ON  submodules.ModuleID = modules.ID
        INNER JOIN `disciplines`    ON  disciplines.ID = modules.DisciplineID
        WHERE submodules.ID = pSubmoduleID AND
              disciplines.AuthorID = pTeacherID
        LIMIT 1;
    IF  vIsLocked != 0 OR
        vNewDiscMaxRate > 100
    THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

    UPDATE `submodules`
        SET     submodules.MaxRate = pMaxRate,
                submodules.Type = pControlType
        WHERE submodules.ID = pSubmoduleID
        LIMIT 1;
    RETURN ROW_COUNT()-1;
PavelBegunkov's avatar
PavelBegunkov committed
END //



DROP FUNCTION IF EXISTS ChangeSubmoduleName//
CREATE FUNCTION `ChangeSubmoduleName` (
        `pTeacherID` INT,
        `pSubmoduleID` INT,
        `pName` VARCHAR(200) CHARSET utf8
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vIsLocked INT DEFAULT -1;
xamgore's avatar
xamgore committed
    SELECT disciplines.IsLocked INTO vIsLocked
        FROM `submodules`
        INNER JOIN `modules`        ON  submodules.ModuleID = modules.ID
        INNER JOIN `disciplines`    ON  disciplines.ID = modules.DisciplineID
        WHERE   disciplines.AuthorID = pTeacherID AND
                submodules.ID = pSubmoduleID
        LIMIT 1;
    IF  vIsLocked != 0 THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

    UPDATE `submodules`
        SET submodules.Name = pName
        WHERE submodules.ID = pSubmoduleID
        LIMIT 1;
PavelBegunkov's avatar
PavelBegunkov committed
    RETURN 0;
END //



DROP FUNCTION IF EXISTS ChangeSubmoduleDescription//
CREATE FUNCTION `ChangeSubmoduleDescription` (
        `pTeacherID` INT,
        `pSubmoduleID` INT,
        `pDescription` VARCHAR(200) CHARSET utf8
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vIsLocked INT DEFAULT -1;
xamgore's avatar
xamgore committed
    SELECT disciplines.IsLocked INTO vIsLocked
        FROM `submodules`
        INNER JOIN `modules`        ON  submodules.ModuleID = modules.ID
        INNER JOIN `disciplines`    ON  disciplines.ID = modules.DisciplineID
        WHERE   disciplines.AuthorID = pTeacherID AND
                submodules.ID = pSubmoduleID
        LIMIT 1;
    IF  vIsLocked != 0 THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

    UPDATE `submodules`
        SET submodules.Description  = pDescription
        WHERE submodules.ID = pSubmoduleID
        LIMIT 1;
PavelBegunkov's avatar
PavelBegunkov committed
    RETURN 0;
END //




DROP FUNCTION IF EXISTS DeleteSubmodule//
CREATE FUNCTION `DeleteSubmodule` (
        `pTeacherID` INT,
        `pSubmoduleID` INT
PavelBegunkov's avatar
PavelBegunkov committed
    ) RETURNS int(11)
    NO SQL
BEGIN
    DECLARE vIsLocked, vModuleID INT DEFAULT -1;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
xamgore's avatar
xamgore committed
    SELECT modules.ID, disciplines.IsLocked
        INTO vModuleID, vIsLocked
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `submodules`
        INNER JOIN `modules` ON modules.ID = submodules.ModuleID
        INNER JOIN `disciplines` ON modules.DisciplineID = disciplines.ID
        WHERE   disciplines.AuthorID = pTeacherID AND
                submodules.ID = pSubmoduleID
        LIMIT 1;
    IF  vIsLocked != 0 THEN
PavelBegunkov's avatar
PavelBegunkov committed
        RETURN -1;
    END IF;

    # handler will catch constraint violation
PavelBegunkov's avatar
PavelBegunkov committed
    DELETE FROM `submodules`
        WHERE submodules.ID = pSubmoduleID
        LIMIT 1;

    # restore continuous ordering
PavelBegunkov's avatar
PavelBegunkov committed
    SET @counter = 0;
    UPDATE `submodules`
        SET submodules.OrderNum = (@counter := @counter + 1)
        WHERE   submodules.ModuleID = vModuleID
        ORDER BY submodules.OrderNum ASC;

    RETURN 0;
END //



DROP FUNCTION IF EXISTS AddSubmodule//
CREATE FUNCTION `AddSubmodule` (
        `pTeacherID` INT,
        `pModuleID` INT,
        `pMaxRate` INT,
PavelBegunkov's avatar
PavelBegunkov committed
        `pName` VARCHAR(200) CHARSET utf8,
        `pDescription` VARCHAR(200) CHARSET utf8,
        `pControlType` VARCHAR(30) CHARSET utf8
    ) RETURNS int(11)
PavelBegunkov's avatar
PavelBegunkov committed
    NO SQL
BEGIN
    DECLARE vOrderNum, vIsLocked INT DEFAULT -1;
    DECLARE vDescription VARCHAR(200) CHARSET utf8 DEFAULT pDescription;
    # DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1;
    # check author and discipline lock
xamgore's avatar
xamgore committed
    SELECT disciplines.IsLocked INTO vIsLocked
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `modules`
        INNER JOIN `disciplines`    ON  disciplines.ID = modules.DisciplineID
PavelBegunkov's avatar
PavelBegunkov committed
        WHERE   disciplines.AuthorID = pTeacherID AND
                modules.ID = pModuleID
        LIMIT 1;
    IF  vIsLocked != 0 THEN
        RETURN -2;
PavelBegunkov's avatar
PavelBegunkov committed
    END IF;

    # get free order
    SET vOrderNum = 0;
    SELECT MAX(submodules.OrderNum) INTO vOrderNum
PavelBegunkov's avatar
PavelBegunkov committed
        FROM `submodules`
        WHERE submodules.ModuleID = pModuleID
        LIMIT 1;
    IF vOrderNum IS NULL THEN
        SET vOrderNum = 0;
    END IF;
    SET vOrderNum = vOrderNum + 1;
    # insert submodule

    IF vDescription = '' THEN
        SET vDescription = NULL;
PavelBegunkov's avatar
PavelBegunkov committed
    END IF;