diff --git a/db/migrations/V13_6__groups_splitting.sql b/db/migrations/V13_6__groups_splitting.sql index 47952dcffe7765720bf65f5efe9e70ed69850999..1a4b483ee5b199b5c6680972d9050b3b0979e5a5 100644 --- a/db/migrations/V13_6__groups_splitting.sql +++ b/db/migrations/V13_6__groups_splitting.sql @@ -6,10 +6,10 @@ START TRANSACTION ; delete from study_groups where id not in ( select distinct GroupID - from students_groups + from students_groups union distinct select distinct GroupID - from disciplines_groups + from disciplines_groups ); delete from specializations @@ -17,11 +17,12 @@ delete from specializations select study_groups.SpecializationID from study_groups ); + -- ========================================== -- create & init `years` table CREATE TABLE IF NOT EXISTS `years` ( - `Num` int(11) NOT NULL, - PRIMARY KEY (`Num`) + `Num` int(11) NOT NULL, + PRIMARY KEY (`Num`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into years (Num) @@ -34,21 +35,19 @@ ALTER TABLE semesters ADD CONSTRAINT semesters_ibfk_1 FOREIGN KEY (`Year`) REFERENCES `years` (`Num`); - - -- ========================================== -- extract semester specific group info -- add table `groups_years` CREATE TABLE IF NOT EXISTS `groups_years` ( - `GroupID` int(11) NOT NULL, - `Year` int(11) NOT NULL, - `SpecializationID` int(11) NOT NULL, - `Name` varchar(50) CHARACTER SET utf8 DEFAULT NULL, - PRIMARY KEY (`Year`, `GroupID`), - KEY `GroupID` (`GroupID`), - KEY `Year` (`Year`), - KEY `SpecializationID` (`SpecializationID`) + `GroupID` int(11) NOT NULL, + `Year` int(11) NOT NULL, + `SpecializationID` int(11) NOT NULL, + `Name` varchar(50) CHARACTER SET utf8 DEFAULT NULL, + PRIMARY KEY (`Year`, `GroupID`), + KEY `GroupID` (`GroupID`), + KEY `Year` (`Year`), + KEY `SpecializationID` (`SpecializationID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE groups_years @@ -57,23 +56,115 @@ ALTER TABLE groups_years ADD CONSTRAINT groups_years_ibfk_3 FOREIGN KEY (`SpecializationID`) REFERENCES `specializations`(`ID`); insert into groups_years (GroupID, Year, SpecializationID, Name) - select study_groups.ID, years.Num, study_groups.SpecializationID, study_groups.Name - from study_groups, years; + select distinct study_groups.ID, semesters.Year, study_groups.SpecializationID, study_groups.Name + from study_groups + inner join students_groups on students_groups.GroupID = study_groups.ID + inner join semesters on semesters.ID = students_groups.SemesterID; + -- ========================================== -- save faculty info + alter table study_groups add column FacultyID int(11) NOT NULL; update study_groups - set FacultyID = (select specializations.FacultyID from specializations - where specializations.id = study_groups.SpecializationID); + set FacultyID = ( + select specializations.FacultyID + from specializations + where specializations.id = study_groups.SpecializationID + ); alter table study_groups add key FacultyID (`FacultyID`), add CONSTRAINT study_groups_ibfk_3 FOREIGN KEY (`FacultyID`) REFERENCES `faculties` (`ID`); +-- ========================================== +-- merge study_groups + +delimiter // + +create procedure mergeStudyGroups_mergeGroup(pNewGroupID int, pFacultyID int, pGradeID int, pGroupNum int) NO SQL +begin + declare stOldGroupID int; + + declare done int default false; + declare cur cursor for + select ID + from study_groups + where + ID <> pNewGroupID and + FacultyID = pFacultyID and + GradeID = pGradeID and + GroupNum = pGroupNum; + declare continue handler for not found set done = true; + + open cur; + + proc_loop: loop + fetch cur into stOldGroupID; + + if done then + leave proc_loop; + end if; + + update students_groups + set GroupID = pNewGroupID + where GroupID = stOldGroupID; + + update ignore disciplines_groups + set GroupID = pNewGroupID + where GroupID = stOldGroupID; + delete from disciplines_groups + where GroupID = stOldGroupID; + + update groups_years + set GroupID = pNewGroupID + where GroupID = stOldGroupID; + + delete from study_groups + where ID = stOldGroupID; + end loop; + + close cur; +end// + +create procedure mergeStudyGroups() +begin + declare stGroupID, stFacultyID, stGradeID, stGroupNum int; + + declare done int default false; + declare cur cursor for + select min(ID), FacultyID, GradeID, GroupNum + from study_groups + group by FacultyID, GradeID, GroupNum + having count(*) > 1; + declare continue handler for not found set done = true; + + open cur; + + proc_loop: loop + fetch cur into stGroupID, stFacultyID, stGradeID, stGroupNum; + + if done then + leave proc_loop; + end if; + + call mergeStudyGroups_mergeGroup(stGroupID, stFacultyID, stGradeID, stGroupNum); + end loop; + + close cur; +end// + +delimiter ; + +call mergeStudyGroups(); + +drop procedure mergeStudyGroups_mergeGroup; +drop procedure mergeStudyGroups; + + -- ========================================== -- clear redundant columns in groups @@ -90,5 +181,3 @@ alter table study_groups add unique key `FacultyGroup`(`FacultyID`,`GradeID`,`GroupNum`); COMMIT ; - - diff --git a/db/migrations/stored/R__procedures.sql b/db/migrations/stored/R__procedures.sql index d2c0719ad599c87e9266b430085f515987a88f10..5b8cd520abee64c03c51e55913642d2d107570ab 100644 --- a/db/migrations/stored/R__procedures.sql +++ b/db/migrations/stored/R__procedures.sql @@ -153,18 +153,21 @@ SELECT grades.* -- ID, Num, Degree DROP PROCEDURE IF EXISTS GetGroups// CREATE PROCEDURE GetGroups ( IN pGradeID INT, - IN pFacultyID INT) + IN pFacultyID INT, + IN pSemesterID INT) READS SQL DATA BEGIN - SELECT view_groups_reduced.GroupID AS 'ID', - view_groups_reduced.GroupNum, - view_groups_reduced.SpecID, - view_groups_reduced.SpecName, - view_groups_reduced.SpecAbbr - FROM view_groups_reduced - WHERE view_groups_reduced.GradeID = pGradeID AND - view_groups_reduced.FacultyID = pFacultyID - ORDER BY view_groups_reduced.GroupNum ASC; + SELECT view_groups.GroupID AS 'ID', + view_groups.GroupNum, + view_groups.SpecID, + view_groups.SpecName, + view_groups.SpecAbbr + FROM view_groups + INNER JOIN semesters ON semesters.ID = pSemesterID + WHERE view_groups.GradeID = pGradeID AND + view_groups.FacultyID = pFacultyID AND + view_groups.Year = semesters.Year + ORDER BY view_groups.GroupNum ASC; END // # get all groups, include attached student's groups diff --git a/db/stored/functions.sql b/db/stored/functions.sql index 2bd240f3bad2711d99643a236ae8c643aae0b73a..60fec6b0f7951a2c2b193c8e885c9d4accf0ef6e 100644 --- a/db/stored/functions.sql +++ b/db/stored/functions.sql @@ -84,29 +84,28 @@ RETURN ( DROP FUNCTION IF EXISTS SetExamPeriodOption// -CREATE FUNCTION SetExamPeriodOption ( +DROP FUNCTION IF EXISTS Discipline_SetExamPeriodOption// +CREATE FUNCTION Discipline_SetExamPeriodOption ( pStudentID INT, pSubmoduleID INT, - pType enum('absence','pass','null') + pType enum('absence', 'pass', 'null') ) RETURNS int(11) NO SQL BEGIN + DECLARE vType INT DEFAULT NULL; DECLARE EXIT HANDLER FOR SQLEXCEPTION RETURN -1; - IF pType = 'null' THEN - DELETE FROM exam_period_options - WHERE exam_period_options.StudentID = pStudentID - AND exam_period_options.SubmoduleID = pSubmoduleID - LIMIT 1; - ELSE - INSERT INTO exam_period_options (StudentID, SubmoduleID, Type) VALUES(pStudentID, pSubmoduleID, pType) - ON DUPLICATE KEY UPDATE - exam_period_options.Type = pType; + IF pType != 'null' THEN + SET vType = pType; END IF; - RETURN ROW_COUNT() - 1; + INSERT INTO exam_period_options (StudentID, SubmoduleID, Type) VALUES(pStudentID, pSubmoduleID, vType) + ON DUPLICATE KEY UPDATE + exam_period_options.Type = vType; + RETURN 0; END // + # check, regular + exam rate == 100 DROP FUNCTION IF EXISTS InternalIsMapCreated// CREATE FUNCTION InternalIsMapCreated (pDisciplineID INT diff --git a/db/stored/procedures.sql b/db/stored/procedures.sql index c6434c7c61083defc513daa2581eed37ac1e221c..f257983067e255329f2c2fa122e48a00c8b2fef3 100644 --- a/db/stored/procedures.sql +++ b/db/stored/procedures.sql @@ -25,27 +25,28 @@ BEGIN CREATE TEMPORARY TABLE tDisciplineStudents AS ( SELECT st.StudentID, - COALESCE(st.Type) AS 'Type' - FROM ( - SELECT disciplines_students.StudentID, - disciplines_students.Type - FROM disciplines_students - WHERE disciplines_students.DisciplineID = pDisciplineID - UNION - SELECT students_groups.StudentID, - NULL AS 'Type' - FROM disciplines_groups - LEFT JOIN students_groups ON students_groups.SemesterID = vSemesterID AND - students_groups.GroupID = disciplines_groups.GroupID AND - students_groups.State <= 'outlet' - WHERE disciplines_groups.DisciplineID = pDisciplineID + COALESCE(st.Type) AS 'Type' + FROM ( + SELECT disciplines_students.StudentID, + disciplines_students.Type + FROM disciplines_students + WHERE disciplines_students.DisciplineID = pDisciplineID + UNION + SELECT students_groups.StudentID, + NULL AS 'Type' + FROM disciplines_groups + LEFT JOIN students_groups ON students_groups.SemesterID = vSemesterID AND + students_groups.GroupID = disciplines_groups.GroupID AND + students_groups.State <= 'outlet' + WHERE disciplines_groups.DisciplineID = pDisciplineID ) as st - GROUP BY st.StudentID + GROUP BY st.StudentID ); RETURN 0; END // + DROP FUNCTION IF EXISTS getDisciplinesForStudentT// CREATE FUNCTION getDisciplinesForStudentT(pStudentID INT, pSemesterID INT) RETURNS INT(11) NO SQL @@ -170,18 +171,21 @@ SELECT grades.* -- ID, Num, Degree DROP PROCEDURE IF EXISTS GetGroups// CREATE PROCEDURE GetGroups ( IN pGradeID INT, - IN pFacultyID INT) + IN pFacultyID INT, + IN pSemesterID INT) READS SQL DATA BEGIN - SELECT view_groups_reduced.GroupID AS 'ID', - view_groups_reduced.GroupNum, - view_groups_reduced.SpecID, - view_groups_reduced.SpecName, - view_groups_reduced.SpecAbbr - FROM view_groups_reduced - WHERE view_groups_reduced.GradeID = pGradeID AND - view_groups_reduced.FacultyID = pFacultyID - ORDER BY view_groups_reduced.GroupNum ASC; + SELECT view_groups.GroupID AS 'ID', + view_groups.GroupNum, + view_groups.SpecID, + view_groups.SpecName, + view_groups.SpecAbbr + FROM view_groups + INNER JOIN semesters ON semesters.ID = pSemesterID + WHERE view_groups.GradeID = pGradeID AND + view_groups.FacultyID = pFacultyID AND + view_groups.Year = semesters.Year + ORDER BY view_groups.GroupNum ASC; END // @@ -698,6 +702,24 @@ BEGIN LIMIT 1; END // +# это обертка процедуры Discipline_GetInfo для случая, когда передается SubmoduleID +DROP PROCEDURE IF EXISTS Discipline_GetInfoBySubmodule // +CREATE PROCEDURE Discipline_GetInfoBySubmodule ( + pSubmoduleID INT +) +READS SQL DATA +BEGIN + DECLARE vDisciplineID INT DEFAULT -1; + SELECT modules.DisciplineID + INTO vDisciplineID + FROM submodules + INNER JOIN modules ON submodules.ModuleID = modules.ID + WHERE submodules.ID = pSubmoduleID + LIMIT 1; + + CALL Discipline_GetInfo(vDisciplineID); +END // + # all disciplines for faculty in current semester DROP PROCEDURE IF EXISTS GetDisciplines// @@ -1126,6 +1148,7 @@ BEGIN view_roadmap.SubmoduleName, view_roadmap.SubmoduleRate AS 'MaxRate', view_roadmap.SubmoduleType, + view_roadmap.SubmoduleOrderNum, rating_table.Rate, rating_table.Date, view_roadmap.ModuleType, diff --git a/db/stored/triggers.sql b/db/stored/triggers.sql index 2764c5bfedda014cbef7cf67d1d8bfc215fb9cc8..244acec3a34c822644c2a8d1f60c659f68b7c38c 100644 --- a/db/stored/triggers.sql +++ b/db/stored/triggers.sql @@ -23,6 +23,8 @@ drop trigger if exists tr_i_submodule// create trigger tr_i_submodule before insert on submodules for each row begin + declare vDisciplineID int default 0; + declare vAccumType, vChangeMax boolean default false; declare vModuleType enum('regular','exam', 'bonus', 'extra') default 'extra'; -- todo: check repeated bonus @@ -31,20 +33,24 @@ begin where modules.ID = new.ModuleID limit 1; - if ( vModuleType in ('regular', 'exam') ) then begin - -- only regular & 1st exam submodules can change Cur/Max rates of discipline - declare vGenModule boolean default (vModuleType != 'exam') or new.OrderNum <=> 1; - declare vDisciplineID int default 0; + -- todo: in operator + if (vModuleType <=> 'regular' or vModuleType <=> 'exam') then begin + set vAccumType = (not vModuleType <=> 'exam'); + -- todo: extract foo set vDisciplineID = ( - select modules.DisciplineID from modules + select disciplines.ID + from modules + inner join disciplines on disciplines.ID = modules.DisciplineID where modules.ID = new.ModuleID limit 1 ); + set vChangeMax = vAccumType || new.OrderNum <=> 1; + update disciplines - set disciplines.CurRate = disciplines.CurRate + if(vGenModule and new.isUsed, new.MaxRate, 0), - disciplines.MaxRate = disciplines.MaxRate + if(vGenModule, new.MaxRate, 0) + set disciplines.CurRate = disciplines.CurRate + if(new.isUsed, new.MaxRate, 0), + disciplines.MaxRate = disciplines.MaxRate + if(vChangeMax, new.MaxRate, 0) where disciplines.ID = vDisciplineID limit 1; end; end if; @@ -54,6 +60,8 @@ drop trigger if exists tr_d_submodule// create trigger tr_d_submodule before delete on submodules for each row begin + declare vDisciplineID int default 0; + declare vAccumType, vChangeMax boolean default false; declare vModuleType enum('regular','exam', 'bonus', 'extra') default 'extra'; -- todo: check repeated bonus @@ -63,20 +71,23 @@ begin limit 1; - if ( vModuleType in ('regular', 'exam') ) then begin - -- only regular & 1st exam submodules can change Cur/Max rates of discipline - declare vGenModule boolean default (vModuleType != 'exam') or old.OrderNum = 1; - declare vDisciplineID int default 0; + if (vModuleType <=> 'regular' or vModuleType <=> 'exam') then begin + set vAccumType = (not vModuleType <=> 'exam'); + -- todo: extract foo set vDisciplineID = ( - select modules.DisciplineID from modules + select disciplines.ID + from modules + inner join disciplines on disciplines.ID = modules.DisciplineID where modules.ID = old.ModuleID limit 1 ); + set vChangeMax = vAccumType || old.OrderNum <=> 1; + update disciplines - set disciplines.CurRate = disciplines.CurRate - if(vGenModule and old.isUsed, old.MaxRate, 0), - disciplines.MaxRate = disciplines.MaxRate - if(vGenModule, old.MaxRate, 0) + set disciplines.CurRate = disciplines.CurRate - if(old.isUsed, old.MaxRate, 0), + disciplines.MaxRate = disciplines.MaxRate - if(vChangeMax, old.MaxRate, 0) where disciplines.ID = vDisciplineID limit 1; end; end if; @@ -87,9 +98,10 @@ drop trigger if exists tr_u_submodule// create trigger tr_u_submodule before update on submodules for each row begin + declare vDisciplineID int default 0; + declare vAccumType, vChangeMaxOld, vChangeMaxNew boolean default false; declare vModuleType enum('regular','exam', 'bonus', 'extra') default 'extra'; - -- forbid submodule's module changing if old.ModuleID != new.ModuleID then signal sqlstate '45000'; end if; @@ -101,23 +113,25 @@ begin limit 1; - if ( vModuleType in ('regular', 'exam') ) then begin - declare vDisciplineID int default 0; - declare vChangeMaxOld, vChangeMaxNew boolean default false; + if (vModuleType <=> 'regular' or vModuleType <=> 'exam') then begin + set vAccumType = (not vModuleType <=> 'exam'); + -- todo: extract foo set vDisciplineID = ( - select modules.DisciplineID from modules - where modules.ID = new.ModuleID + select disciplines.ID + from modules + inner join disciplines on disciplines.ID = modules.DisciplineID + where modules.ID = old.ModuleID limit 1 ); - set vChangeMaxOld = (vModuleType != 'exam') or old.OrderNum = 1; - set vChangeMaxNew = (vModuleType != 'exam') or new.OrderNum = 1; + set vChangeMaxOld = vAccumType || old.OrderNum <=> 1; + set vChangeMaxNew = vAccumType || new.OrderNum <=> 1; update disciplines set disciplines.CurRate = disciplines.CurRate - - if(vChangeMaxOld and old.isUsed, old.MaxRate, 0) - + if(vChangeMaxNew and new.isUsed, new.MaxRate, 0), + - if(old.isUsed, old.MaxRate, 0) + + if(new.isUsed, new.MaxRate, 0), disciplines.MaxRate = disciplines.MaxRate - if(vChangeMaxOld, old.MaxRate, 0) + if(vChangeMaxNew, new.MaxRate, 0) diff --git a/media/js/transfer.js b/media/js/transfer.js index 8a011233998c69ab5dac130f385a5ad8edc10429..a0edfd8fc8d21cf11119743ad9abeccc3c891f89 100644 --- a/media/js/transfer.js +++ b/media/js/transfer.js @@ -8,36 +8,38 @@ function GroupFunction(type) { // var jItemContainer = $('.TransferListItem'); var jList = $("#" + type + "ItemsList"); - jGrades.find('option[value=-1]').attr('selected', 'selected'); - jGroupSelect.find('option[value=-1]').attr('selected', 'selected'); + jGrades.find('option[value=-1]').prop('selected', true); + jGroupSelect.turnOff(); + jGroupSelect.find('option[value=0]').prop('selected', true); jSemesters.change(function () { var sem = jSemesters.find('option:selected'); - sem.hasClass('current') ? $(this).addClass('Current') : $(this).removeClass('Current') ; - if (sem.val() != 0) { - jGrades.prop('disabled', false); - } else { - jGrades.prop('disabled', true); - jGroupSelect.prop('disabled', true); - } - - // clear list - jList.html(''); - }); + if (sem.hasClass('current')) + jSemesters.addClass('Current'); + else + jSemesters.removeClass('Current'); - let groupSelect = getGroupLoader(jGroupSelect, - () => ({FacultyID: settings.facultyID, 'GradeID': +jGrades.val()}) - ).setOnChange(OptionLoader.stubFoo); + jGrades.find('option[value=-1]').prop('selected', true); + jGroupSelect.turnOff(); + jGroupSelect.find('option[value=0]').prop('selected', true); + }); - jGrades.change(() => { - let gradeID = jGrades.val(); - if (gradeID) + jGrades.change(function () { + if (+jGrades.val() != -1) { groupSelect.reload(); - else - groupSelect.turnOff(); + jList.html(''); + } else { + jSemesters.change(); + } }); + let groupSelect = getGroupLoader(jGroupSelect, () => ({ + FacultyID: settings.facultyID, + SemesterID: +jSemesters.find('option:selected').val(), + GradeID: +jGrades.val() + })); + var jButtonSelect = $('#SelectAll' + type); var jStudentsList = $('#StudentList' + type); var jButtonDeselect = $('#DeselectAll' + type); diff --git a/~dev_rating/application/classes/Controller/Handler/Map.php b/~dev_rating/application/classes/Controller/Handler/Map.php index 2197bcfb8f0a923d2d4eb2ae82a9ec47521a2a48..d3c639202f4a181b4f13076970feaaa7192d0e4f 100644 --- a/~dev_rating/application/classes/Controller/Handler/Map.php +++ b/~dev_rating/application/classes/Controller/Handler/Map.php @@ -164,7 +164,7 @@ class Controller_Handler_Map extends Controller_Handler public function action_GetGroups() { $faculty = Model_Faculty::with($_POST['FacultyID']); - $groups = $faculty->getGroups($_POST['GradeID']); + $groups = $faculty->getGroups($_POST['GradeID'], $_POST['SemesterID']); $this->response->body(json_encode($groups)); } diff --git a/~dev_rating/application/classes/Model/Faculty.php b/~dev_rating/application/classes/Model/Faculty.php index e29da429e26bad52cdfbe0fc1bb09735287c54a6..6ab9e0d7cf60fde9819ef31631e48b57aebb7d29 100644 --- a/~dev_rating/application/classes/Model/Faculty.php +++ b/~dev_rating/application/classes/Model/Faculty.php @@ -81,10 +81,11 @@ class Model_Faculty extends Model */ public function getGroups($grade, $semesterID = null) { $semesterID = $semesterID ?: User::instance()->SemesterID; - $sql = 'CALL `GetGroups`(:grade, :id)'; + $sql = 'CALL `GetGroups`(:grade, :facultyID, :semesterID)'; return DB::query(Database::SELECT, $sql) ->param(':grade', (int) $grade) - ->param(':id', $this->ID) + ->param(':facultyID', $this->ID) + ->param(':semesterID', $semesterID) ->execute()->as_array(); }