Version 20.94.5: Jun 25, 2021 Queries moved to module swad_group_database.

This commit is contained in:
acanas 2021-06-25 20:05:58 +02:00
parent 0be1d7ba16
commit 6a8c7b9efe
9 changed files with 358 additions and 294 deletions

View File

@ -59,6 +59,7 @@
#include "swad_forum.h"
#include "swad_game.h"
#include "swad_global.h"
#include "swad_group_database.h"
#include "swad_hierarchy.h"
#include "swad_holiday.h"
#include "swad_ID.h"
@ -4113,7 +4114,7 @@ void Act_AdjustCurrentAction (void)
the only action possible
is show a form to register in groups *****/
if (JustAfterLogin) // Only after login because the following query may be slow
if (Grp_GetIfAvailableGrpTyp (-1L)) // This query may be slow
if (Grp_DB_CheckIfAvailableGrpTyp (-1L)) // This query may be slow
{
Gbl.Action.Act = ActReqSelGrp;
Tab_SetCurrentTab ();

View File

@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
*/
#define Log_PLATFORM_VERSION "SWAD 20.94.4 (2021-06-24)"
#define Log_PLATFORM_VERSION "SWAD 20.94.5 (2021-06-25)"
#define CSS_FILE "swad20.45.css"
#define JS_FILE "swad20.69.1.js"
/*
TODO: Rename CENTRE to CENTER in help wiki.
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
Version 20.94.5: Jun 25, 2021 Queries moved to module swad_group_database. (313686 lines)
Version 20.94.4: Jun 24, 2021 Queries moved to module swad_group_database. (313637 lines)
Version 20.94.3: Jun 18, 2021 Queries moved to module swad_group_database. (313602 lines)
Version 20.94.2: Jun 18, 2021 Queries moved to module swad_group_database. (313557 lines)

View File

@ -51,6 +51,7 @@
#include "swad_project.h"
#include "swad_setting.h"
#include "swad_survey.h"
#include "swad_timetable.h"
/*****************************************************************************/
/*************************** Private constants *******************************/
@ -135,7 +136,7 @@ static void Grp_PutFormToCreateGroupType (void);
static void Grp_PutFormToCreateGroup (const struct Roo_Rooms *Rooms);
static void Grp_GetDataOfGroupTypeByCod (struct GroupType *GrpTyp);
static bool Grp_GetMultipleEnrolmentOfAGroupType (long GrpTypCod);
static void Grp_GetLstCodGrpsUsrBelongs (long CrsCod,long GrpTypCod,long UsrCod,
static void Grp_GetLstCodGrpsUsrBelongs (long UsrCod,long GrpTypCod,
struct ListCodGrps *LstGrps);
static bool Grp_CheckIfGrpIsInList (long GrpCod,struct ListCodGrps *LstGrps);
static bool Grp_CheckIfOpenTimeInTheFuture (time_t OpenTimeUTC);
@ -536,8 +537,8 @@ void Grp_GetParCodsSeveralGrpsToShowUsrs (void)
{
/***** I I haven't selected any group, show by default the groups I belong to *****/
/* Get list of groups of all types in current course I belong to */
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,-1L,
Gbl.Usrs.Me.UsrDat.UsrCod,&LstGrpsIBelong);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Me.UsrDat.UsrCod,-1L,
&LstGrpsIBelong);
if (LstGrpsIBelong.NumGrps)
{
@ -778,8 +779,8 @@ bool Grp_ChangeMyGrpsAtomically (struct ListCodGrps *LstGrpsIWant)
Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
/***** Query in the database the group codes which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,-1L,
Gbl.Usrs.Me.UsrDat.UsrCod,&LstGrpsIBelong);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Me.UsrDat.UsrCod,-1L,
&LstGrpsIBelong);
if (Gbl.Usrs.Me.Role.Logged == Rol_STD)
{
@ -919,8 +920,8 @@ void Grp_ChangeGrpsOtherUsrAtomically (struct ListCodGrps *LstGrpsUsrWants)
Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
/***** Query in the database the group codes which user belongs to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,-1L,
Gbl.Usrs.Other.UsrDat.UsrCod,&LstGrpsUsrBelongs);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Other.UsrDat.UsrCod,-1L,
&LstGrpsUsrBelongs);
/***** Go across the list of groups user belongs to, removing those groups that are not present in the list of groups user wants to belong to *****/
for (NumGrpUsrBelongs = 0;
@ -1079,8 +1080,8 @@ void Grp_RegisterUsrIntoGroups (struct UsrData *UsrDat,struct ListCodGrps *LstGr
/***** Query in the database the group codes of any group of this type the student belongs to *****/
LstGrpsHeBelongs.NumGrps = 0; // Initialized to avoid bug reported by Coverity
LstGrpsHeBelongs.GrpCods = NULL; // Initialized to avoid bug reported by Coverity
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod,
UsrDat->UsrCod,&LstGrpsHeBelongs);
Grp_GetLstCodGrpsUsrBelongs (UsrDat->UsrCod,Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod,
&LstGrpsHeBelongs);
/***** For each group selected by me... *****/
for (NumGrpSel = 0;
@ -1144,8 +1145,8 @@ unsigned Grp_RemoveUsrFromGroups (struct UsrData *UsrDat,struct ListCodGrps *Lst
unsigned NumGrpsHeIsRemoved = 0;
/***** Query in the database the group codes of any group the user belongs to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,-1L,
UsrDat->UsrCod,&LstGrpsHeBelongs);
Grp_GetLstCodGrpsUsrBelongs (UsrDat->UsrCod,-1L,
&LstGrpsHeBelongs);
/***** For each group selected by me... *****/
for (NumGrpSel = 0;
@ -1646,8 +1647,8 @@ void Grp_ListGrpsToEditAsgAttSvyEvtMch (struct GroupType *GrpTyp,
Grp_WriteGrpHead (GrpTyp);
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,GrpTyp->GrpTypCod,
Gbl.Usrs.Me.UsrDat.UsrCod,&LstGrpsIBelong);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Me.UsrDat.UsrCod,GrpTyp->GrpTypCod,
&LstGrpsIBelong);
/***** List the groups *****/
for (NumGrpThisType = 0;
@ -1823,9 +1824,9 @@ static void Grp_ShowWarningToStdsToChangeGrps (void)
// If there are groups of this type...
if (GrpTyp->NumGrps)
// If I don't belong to any group
if (!Grp_DB_CheckIfIBelongToGrpsOfType (GrpTyp->GrpTypCod)) // Fast check (not necesary, but avoid slow check)
if (!Grp_DB_CheckIfIBelongToGrpsOfType (GrpTyp->GrpTypCod)) // Fast check (not necesary, but avoid slow check)
// If there is any group of this type available
if (Grp_GetIfAvailableGrpTyp (GrpTyp->GrpTypCod)) // Slow check
if (Grp_DB_CheckIfAvailableGrpTyp (GrpTyp->GrpTypCod)) // Slow check
{
if (GrpTyp->MandatoryEnrolment)
Ale_ShowAlert (Ale_WARNING,GrpTyp->MultipleEnrolment ? Txt_You_have_to_register_compulsorily_at_least_in_one_group_of_type_X :
@ -1860,8 +1861,8 @@ static bool Grp_ListGrpsForChangeMySelection (struct GroupType *GrpTyp,
Grp_WriteGrpHead (GrpTyp);
/***** Query in the database the group of this type that I belong to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,GrpTyp->GrpTypCod,
Gbl.Usrs.Me.UsrDat.UsrCod,&LstGrpsIBelong);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Me.UsrDat.UsrCod,GrpTyp->GrpTypCod,
&LstGrpsIBelong);
*NumGrpsThisTypeIBelong = LstGrpsIBelong.NumGrps;
/***** Check if I can change my selection *****/
@ -2065,8 +2066,8 @@ static void Grp_ListGrpsToAddOrRemUsrs (struct GroupType *GrpTyp,long UsrCod)
/***** Query the groups of this type which the user belongs to *****/
if (UsrCod > 0)
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,GrpTyp->GrpTypCod,
Gbl.Usrs.Other.UsrDat.UsrCod,&LstGrpsUsrBelongs);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Other.UsrDat.UsrCod,GrpTyp->GrpTypCod,
&LstGrpsUsrBelongs);
/***** List the groups *****/
for (NumGrpThisType = 0;
@ -2131,8 +2132,8 @@ static void Grp_ListGrpsForMultipleSelection (struct GroupType *GrpTyp,
Grp_WriteGrpHead (GrpTyp);
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs (Gbl.Hierarchy.Crs.CrsCod,GrpTyp->GrpTypCod,
Gbl.Usrs.Me.UsrDat.UsrCod,&LstGrpsIBelong);
Grp_GetLstCodGrpsUsrBelongs (Gbl.Usrs.Me.UsrDat.UsrCod,GrpTyp->GrpTypCod,
&LstGrpsIBelong);
/***** List the groups of this type *****/
for (NumGrpThisType = 0;
@ -3016,7 +3017,7 @@ bool Grp_GetIfIBelongToGrp (long GrpCod)
}
/*****************************************************************************/
/*************** Check if a user belongs to any of my courses ****************/
/***** Check if a user belongs to any of my groups in the current course *****/
/*****************************************************************************/
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (void)
@ -3076,175 +3077,26 @@ bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat)
/***** 9. Slow check: Get if user shares any group in this course with me from database *****/
/* Check if user shares any group with me */
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.UsrCod = UsrDat->UsrCod;
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares =
(DB_QueryCOUNT ("can not check if a user shares any group"
" in the current course with you",
"SELECT COUNT(*)"
" FROM grp_users"
" WHERE UsrCod=%ld"
" AND GrpCod IN"
" (SELECT grp_users.GrpCod"
" FROM grp_users,"
"grp_groups,"
"grp_types"
" WHERE grp_users.UsrCod=%ld"
" AND grp_users.GrpCod=grp_groups.GrpCod"
" AND grp_groups.GrpTypCod=grp_types.GrpTypCod"
" AND grp_types.CrsCod=%ld)",
UsrDat->UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Hierarchy.Crs.CrsCod) != 0);
Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares = Grp_DB_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (UsrDat->UsrCod);
return Gbl.Cache.UsrSharesAnyOfMyGrpsInCurrentCrs.Shares;
}
/*****************************************************************************/
/**** Get if any group in group-type/this-course is open and has vacants *****/
/*****************************************************************************/
// If GrpTypCod > 0 ==> restrict to the given group type, mandatory or not
// If GrpTypCod <= 0 ==> all mandatory group types in the current course
bool Grp_GetIfAvailableGrpTyp (long GrpTypCod)
{
unsigned NumGrpTypes;
char *SubQueryGrpTypes;
if (GrpTypCod > 0) // restrict to the given group type, mandatory or not
{
if (asprintf (&SubQueryGrpTypes,"grp_types.GrpTypCod=%ld",
GrpTypCod) < 0)
Err_NotEnoughMemoryExit ();
}
else // all mandatory group types in the current course
{
if (asprintf (&SubQueryGrpTypes,"grp_types.CrsCod=%ld"
" AND grp_types.Mandatory='Y'",
Gbl.Hierarchy.Crs.CrsCod) < 0)
Err_NotEnoughMemoryExit ();
}
/***** Get the number of types of group in this course
with one or more open groups with vacants, from database *****/
NumGrpTypes = (unsigned)
DB_QueryCOUNT ("can not check if there has available mandatory group types",
"SELECT COUNT(GrpTypCod)"
" FROM ("
// Available mandatory groups with students
"SELECT GrpTypCod"
" FROM (SELECT grp_types.GrpTypCod AS GrpTypCod,"
"COUNT(*) AS NumStudents,"
"grp_groups.MaxStudents as MaxStudents"
" FROM grp_types,"
"grp_groups,"
"grp_users,"
"crs_users"
" WHERE %s" // Which group types?
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.Open='Y'" // Open
" AND grp_groups.MaxStudents>0" // Admits students
" AND grp_types.CrsCod=crs_users.CrsCod"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=crs_users.UsrCod"
" AND crs_users.Role=%u" // Student
" GROUP BY grp_groups.GrpCod"
" HAVING NumStudents<MaxStudents" // Not full
") AS available_grp_types_with_stds"
" UNION "
// Available mandatory groups...
"SELECT grp_types.GrpTypCod AS GrpTypCod"
" FROM grp_types,"
"grp_groups"
" WHERE %s" // Which group types?
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.Open='Y'" // Open
" AND grp_groups.MaxStudents>0" // Admits students
// ...without students
" AND grp_groups.GrpCod NOT IN"
" (SELECT grp_users.GrpCod"
" FROM crs_users,"
"grp_users"
" WHERE crs_users.CrsCod=%ld"
" AND crs_users.Role=%u" // Student
" AND crs_users.UsrCod=grp_users.UsrCod)"
") AS available_grp_types"
// ...to which I don't belong
" WHERE GrpTypCod NOT IN"
" (SELECT grp_types.GrpTypCod"
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE %s" // Which group types?
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.Open='Y'" // Open
" AND grp_groups.MaxStudents>0" // Admits students
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld)", // I belong
SubQueryGrpTypes,(unsigned) Rol_STD,
SubQueryGrpTypes,
Gbl.Hierarchy.Crs.CrsCod,(unsigned) Rol_STD,
SubQueryGrpTypes,Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Free allocated memory for subquery *****/
free (SubQueryGrpTypes);
return (NumGrpTypes != 0);
}
/*****************************************************************************/
/****** Query list of group codes of a type to which a user belongs to *******/
/*****************************************************************************/
// If CrsCod < 0 ==> get the groups from all the user's courses
// If GrpTypCod < 0 ==> get the groups of any type
static void Grp_GetLstCodGrpsUsrBelongs (long CrsCod,long GrpTypCod,
long UsrCod,struct ListCodGrps *LstGrps)
static void Grp_GetLstCodGrpsUsrBelongs (long UsrCod,long GrpTypCod,
struct ListCodGrps *LstGrps)
{
MYSQL_RES *mysql_res;
unsigned NumGrp;
/***** Get groups which a user belong to from database *****/
if (CrsCod < 0) // Query the groups from all the user's courses
LstGrps->NumGrps = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get the groups which a user belongs to",
"SELECT GrpCod" // row[0]
" FROM grp_users"
" WHERE UsrCod=%ld", // Groups will be unordered
UsrCod);
else if (GrpTypCod < 0) // Query the groups of any type in the course
LstGrps->NumGrps = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get the groups which a user belongs to",
"SELECT grp_groups.GrpCod" // row[0]
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE grp_types.CrsCod=%ld"
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_types.GrpTypName,"
"grp_groups.GrpName",
Gbl.Hierarchy.Crs.CrsCod,
UsrCod);
else // Query only the groups of specified type in the course
LstGrps->NumGrps = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get the groups which a user belongs to",
"SELECT grp_groups.GrpCod" // row[0]
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE grp_types.CrsCod=%ld"
" AND grp_types.GrpTypCod=%ld"
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_groups.GrpName",
Gbl.Hierarchy.Crs.CrsCod,
GrpTypCod,
UsrCod);
if (GrpTypCod < 0) // Query the groups of any type in the current course
LstGrps->NumGrps = Grp_DB_GetLstCodGrpsOfAnyTypeInCurrentCrsUsrBelongs (&mysql_res,UsrCod);
else // Query only the groups of specified type in the current course
LstGrps->NumGrps = Grp_DB_GetLstCodGrpsOfATypeInCurrentCrsUsrBelongs (&mysql_res,UsrCod,GrpTypCod);
/***** Get the groups *****/
if (LstGrps->NumGrps)
@ -3274,22 +3126,8 @@ void Grp_GetLstCodGrpsWithFileZonesIBelong (struct ListCodGrps *LstGrps)
MYSQL_RES *mysql_res;
unsigned NumGrp;
/***** Get groups which I belong to from database *****/
LstGrps->NumGrps = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get the groups which you belong to",
"SELECT grp_groups.GrpCod" // row[0]
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE grp_types.CrsCod=%ld"
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.FileZones='Y'"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_types.GrpTypName,"
"grp_groups.GrpName",
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Get groups with file zones which I belong to from database *****/
LstGrps->NumGrps = Grp_DB_GetLstCodGrpsWithFileZonesInCurrentCrsIBelong (&mysql_res);
/***** Get the groups *****/
if (LstGrps->NumGrps)
@ -3323,6 +3161,7 @@ static bool Grp_CheckIfGrpIsInList (long GrpCod,struct ListCodGrps *LstGrps)
NumGrp++)
if (GrpCod == LstGrps->GrpCods[NumGrp])
return true;
return false;
}
@ -3330,7 +3169,7 @@ static bool Grp_CheckIfGrpIsInList (long GrpCod,struct ListCodGrps *LstGrps)
/********** Query names of groups of a type which user belongs to ************/
/*****************************************************************************/
void Grp_GetNamesGrpsStdBelongsTo (long GrpTypCod,long UsrCod,char *GroupNames)
void Grp_GetNamesGrpsUsrBelongsTo (long UsrCod,long GrpTypCod,char *GroupNames)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
@ -3340,17 +3179,7 @@ void Grp_GetNamesGrpsStdBelongsTo (long GrpTypCod,long UsrCod,char *GroupNames)
Gbl.Crs.Grps.GrpTypes.NumGrpsTotal;
/***** Get the names of groups which a user belongs to, from database *****/
NumGrps = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get names of groups a user belongs to",
"SELECT grp_groups.GrpName" // row[0]
" FROM grp_groups,"
"grp_users"
" WHERE grp_groups.GrpTypCod=%ld"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_groups.GrpName",
GrpTypCod,
UsrCod);
NumGrps = Grp_DB_GetNamesGrpsUsrBelongsTo (&mysql_res,UsrCod,GrpTypCod);
/***** Get the groups *****/
GroupNames[0] = '\0';
@ -3684,15 +3513,8 @@ static void Grp_RemoveGroupTypeCompletely (void)
/***** Remove the associations of surveys to groups of this type *****/
Svy_RemoveGroupsOfType (Gbl.Crs.Grps.GrpTyp.GrpTypCod);
/***** Change all groups of this type in course timetable *****/
DB_QueryUPDATE ("can not update all groups of a type in course timetable",
"UPDATE tmt_courses"
" SET GrpCod=-1"
" WHERE GrpCod IN"
" (SELECT GrpCod"
" FROM grp_groups"
" WHERE GrpTypCod=%ld)",
Gbl.Crs.Grps.GrpTyp.GrpTypCod);
/***** Orphan all groups of this type in course timetable *****/
Tmt_DB_OrphanAllGrpsOfATypeInCrsTimeTable (Gbl.Crs.Grps.GrpTyp.GrpTypCod);
/***** Remove all the students in groups of this type *****/
DB_QueryDELETE ("can not remove users from all groups of a type",

View File

@ -200,10 +200,8 @@ bool Grp_GetIfIBelongToGrp (long GrpCod);
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs (void);
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (const struct UsrData *UsrDat);
bool Grp_GetIfAvailableGrpTyp (long GrpTypCod);
void Grp_GetLstCodGrpsWithFileZonesIBelong (struct ListCodGrps *LstGrps);
void Grp_GetNamesGrpsStdBelongsTo (long GrpTypCod,long UsrCod,char *GrpNames);
void Grp_GetNamesGrpsUsrBelongsTo (long UsrCod,long GrpTypCod,char *GroupNames);
void Grp_ReceiveFormNewGrpTyp (void);
void Grp_ReceiveFormNewGrp (void);
void Grp_ReqRemGroupType (void);

View File

@ -25,9 +25,9 @@
/*********************************** Headers *********************************/
/*****************************************************************************/
// #define _GNU_SOURCE // For asprintf
#define _GNU_SOURCE // For asprintf
// #include <stddef.h> // For NULL
// #include <stdio.h> // For asprintf
#include <stdio.h> // For asprintf
// #include <stdlib.h> // For exit, system, malloc, free, rand, etc.
// #include <string.h> // For string functions
@ -355,6 +355,32 @@ bool Grp_DB_CheckIfIBelongToGrp (long GrpCod)
Gbl.Usrs.Me.UsrDat.UsrCod) != 0);
}
/*****************************************************************************/
/***** Check if a user belongs to any of my groups in the current course *****/
/*****************************************************************************/
unsigned Grp_DB_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (long UsrCod)
{
return (unsigned)
(DB_QueryCOUNT ("can not check if a user shares any group"
" in the current course with you",
"SELECT COUNT(*)"
" FROM grp_users"
" WHERE UsrCod=%ld"
" AND GrpCod IN"
" (SELECT grp_users.GrpCod"
" FROM grp_users,"
"grp_groups,"
"grp_types"
" WHERE grp_users.UsrCod=%ld"
" AND grp_users.GrpCod=grp_groups.GrpCod"
" AND grp_groups.GrpTypCod=grp_types.GrpTypCod"
" AND grp_types.CrsCod=%ld)",
UsrCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.Hierarchy.Crs.CrsCod) != 0);
}
/*****************************************************************************/
/************** Get group types with groups in current course ****************/
/*****************************************************************************/
@ -491,6 +517,96 @@ unsigned Grp_DB_GetGrpsOfType (MYSQL_RES **mysql_res,long GrpTypCod)
GrpTypCod);
}
/*****************************************************************************/
/*********** Get the list of group codes of any type **************/
/*********** to which a user belongs to (in the current course) **************/
/*****************************************************************************/
unsigned Grp_DB_GetLstCodGrpsOfAnyTypeInCurrentCrsUsrBelongs (MYSQL_RES **mysql_res,long UsrCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get the groups which a user belongs to",
"SELECT grp_groups.GrpCod" // row[0]
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE grp_types.CrsCod=%ld"
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_types.GrpTypName,"
"grp_groups.GrpName",
Gbl.Hierarchy.Crs.CrsCod,
UsrCod);
}
/*****************************************************************************/
/************ Get the list of group codes of a type *************/
/************ to which a user belongs to (in the current course) *************/
/*****************************************************************************/
unsigned Grp_DB_GetLstCodGrpsOfATypeInCurrentCrsUsrBelongs (MYSQL_RES **mysql_res,long UsrCod,long GrpTypCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get the groups which a user belongs to",
"SELECT grp_groups.GrpCod" // row[0]
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE grp_types.CrsCod=%ld"
" AND grp_types.GrpTypCod=%ld"
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_groups.GrpName",
Gbl.Hierarchy.Crs.CrsCod,
GrpTypCod,
UsrCod);
}
/*****************************************************************************/
/**************** Get groups with file zones which I belong ******************/
/*****************************************************************************/
unsigned Grp_DB_GetLstCodGrpsWithFileZonesInCurrentCrsIBelong (MYSQL_RES **mysql_res)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get the groups which you belong to",
"SELECT grp_groups.GrpCod" // row[0]
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE grp_types.CrsCod=%ld"
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.FileZones='Y'"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_types.GrpTypName,"
"grp_groups.GrpName",
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
}
/*****************************************************************************/
/********** Query names of groups of a type which user belongs to ************/
/*****************************************************************************/
unsigned Grp_DB_GetNamesGrpsUsrBelongsTo (MYSQL_RES **mysql_res,
long UsrCod,long GrpTypCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get names of groups a user belongs to",
"SELECT grp_groups.GrpName" // row[0]
" FROM grp_groups,"
"grp_users"
" WHERE grp_groups.GrpTypCod=%ld"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld"
" ORDER BY grp_groups.GrpName",
GrpTypCod,
UsrCod);
}
/*****************************************************************************/
/********************** Get the type of group of a group *********************/
/*****************************************************************************/
@ -577,6 +693,103 @@ void Grp_DB_ClearMustBeOpened (long GrpTypCod)
GrpTypCod);
}
/*****************************************************************************/
/**** Get if any group in group-type/this-course is open and has vacants *****/
/*****************************************************************************/
// If GrpTypCod > 0 ==> restrict to the given group type, mandatory or not
// If GrpTypCod <= 0 ==> all mandatory group types in the current course
bool Grp_DB_CheckIfAvailableGrpTyp (long GrpTypCod)
{
unsigned NumGrpTypes;
char *SubQueryGrpTypes;
if (GrpTypCod > 0) // restrict to the given group type, mandatory or not
{
if (asprintf (&SubQueryGrpTypes,"grp_types.GrpTypCod=%ld",
GrpTypCod) < 0)
Err_NotEnoughMemoryExit ();
}
else // all mandatory group types in the current course
{
if (asprintf (&SubQueryGrpTypes,"grp_types.CrsCod=%ld"
" AND grp_types.Mandatory='Y'",
Gbl.Hierarchy.Crs.CrsCod) < 0)
Err_NotEnoughMemoryExit ();
}
/***** Get the number of types of group in this course
with one or more open groups with vacants, from database *****/
NumGrpTypes = (unsigned)
DB_QueryCOUNT ("can not check if there has available mandatory group types",
"SELECT COUNT(GrpTypCod)"
" FROM ("
// Available mandatory groups with students
"SELECT GrpTypCod"
" FROM (SELECT grp_types.GrpTypCod AS GrpTypCod,"
"COUNT(*) AS NumStudents,"
"grp_groups.MaxStudents as MaxStudents"
" FROM grp_types,"
"grp_groups,"
"grp_users,"
"crs_users"
" WHERE %s" // Which group types?
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.Open='Y'" // Open
" AND grp_groups.MaxStudents>0" // Admits students
" AND grp_types.CrsCod=crs_users.CrsCod"
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=crs_users.UsrCod"
" AND crs_users.Role=%u" // Student
" GROUP BY grp_groups.GrpCod"
" HAVING NumStudents<MaxStudents" // Not full
") AS available_grp_types_with_stds"
" UNION "
// Available mandatory groups...
"SELECT grp_types.GrpTypCod AS GrpTypCod"
" FROM grp_types,"
"grp_groups"
" WHERE %s" // Which group types?
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.Open='Y'" // Open
" AND grp_groups.MaxStudents>0" // Admits students
// ...without students
" AND grp_groups.GrpCod NOT IN"
" (SELECT grp_users.GrpCod"
" FROM crs_users,"
"grp_users"
" WHERE crs_users.CrsCod=%ld"
" AND crs_users.Role=%u" // Student
" AND crs_users.UsrCod=grp_users.UsrCod)"
") AS available_grp_types"
// ...to which I don't belong
" WHERE GrpTypCod NOT IN"
" (SELECT grp_types.GrpTypCod"
" FROM grp_types,"
"grp_groups,"
"grp_users"
" WHERE %s" // Which group types?
" AND grp_types.GrpTypCod=grp_groups.GrpTypCod"
" AND grp_groups.Open='Y'" // Open
" AND grp_groups.MaxStudents>0" // Admits students
" AND grp_groups.GrpCod=grp_users.GrpCod"
" AND grp_users.UsrCod=%ld)", // I belong
SubQueryGrpTypes,(unsigned) Rol_STD,
SubQueryGrpTypes,
Gbl.Hierarchy.Crs.CrsCod,(unsigned) Rol_STD,
SubQueryGrpTypes,Gbl.Usrs.Me.UsrDat.UsrCod);
/***** Free allocated memory for subquery *****/
free (SubQueryGrpTypes);
return (NumGrpTypes != 0);
}
/*****************************************************************************/
/*************************** Rename a group type *****************************/
/*****************************************************************************/

View File

@ -65,6 +65,7 @@ unsigned Grp_DB_CountNumUsrsInNoGrpsOfType (Rol_Role_t Role,long GrpTypCod);
bool Grp_DB_CheckIfIBelongToGrpsOfType (long GrpTypCod);
bool Grp_DB_CheckIfIBelongToGrp (long GrpCod);
unsigned Grp_DB_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs (long UsrCod);
unsigned Grp_DB_GetGrpTypesWithGrpsInCurrentCrs (MYSQL_RES **mysql_res);
unsigned Grp_DB_GetAllGrpTypesInCurrentCrs (MYSQL_RES **mysql_res);
@ -75,6 +76,13 @@ unsigned Grp_DB_CountNumGrpsInCurrentCrs (void);
unsigned Grp_DB_CountNumGrpsInThisCrsOfType (long GrpTypCod);
unsigned Grp_DB_GetGrpsOfType (MYSQL_RES **mysql_res,long GrpTypCod);
unsigned Grp_DB_GetLstCodGrpsInAllCrssUsrBelongs (MYSQL_RES **mysql_res,long UsrCod);
unsigned Grp_DB_GetLstCodGrpsOfAnyTypeInCurrentCrsUsrBelongs (MYSQL_RES **mysql_res,long UsrCod);
unsigned Grp_DB_GetLstCodGrpsOfATypeInCurrentCrsUsrBelongs (MYSQL_RES **mysql_res,long UsrCod,long GrpTypCod);
unsigned Grp_DB_GetLstCodGrpsWithFileZonesInCurrentCrsIBelong (MYSQL_RES **mysql_res);
unsigned Grp_DB_GetNamesGrpsUsrBelongsTo (MYSQL_RES **mysql_res,
long UsrCod,long GrpTypCod);
long Grp_DB_GetGrpTypeFromGrp (long GrpCod);
bool Grp_DB_CheckIfAssociatedToGrp (const char *Table,const char *Field,
@ -84,6 +92,8 @@ bool Grp_DB_CheckIfAssociatedToGrps (const char *Table,const char *Field,long Co
void Grp_DB_OpenGrpsOfType (long GrpTypCod);
void Grp_DB_ClearMustBeOpened (long GrpTypCod);
bool Grp_DB_CheckIfAvailableGrpTyp (long GrpTypCod);
void Grp_DB_RenameGrpTyp (long GrpTypCod,
const char NewNameGrpTyp[Grp_MAX_BYTES_GROUP_TYPE_NAME + 1]);
void Grp_DB_RenameGrp (long GrpCod,

View File

@ -1823,3 +1823,19 @@ static void Tmt_TimeTableDrawCell (const struct Tmt_Timetable *Timetable,
/***** End cell *****/
HTM_TD_End ();
}
/*****************************************************************************/
/************ Orphan all groups of this type in course timetable *************/
/*****************************************************************************/
void Tmt_DB_OrphanAllGrpsOfATypeInCrsTimeTable (long GrpTypCod)
{
DB_QueryUPDATE ("can not update all groups of a type in course timetable",
"UPDATE tmt_courses"
" SET GrpCod=-1"
" WHERE GrpCod IN"
" (SELECT GrpCod"
" FROM grp_groups"
" WHERE GrpTypCod=%ld)",
Gbl.Crs.Grps.GrpTyp.GrpTypCod);
}

View File

@ -115,4 +115,6 @@ void Tmt_EditCrsTimeTable (void);
void Tmt_EditMyTutTimeTable (void);
void Tmt_ShowTimeTable (struct Tmt_Timetable *Timetable,long UsrCod);
void Tmt_DB_OrphanAllGrpsOfATypeInCrsTimeTable (long GrpTypCod);
#endif

View File

@ -3849,84 +3849,85 @@ static void Usr_WriteRowStdAllData (struct UsrData *UsrDat,char *GroupNames)
/***** Start row *****/
HTM_TR_Begin (NULL);
if (Gbl.Usrs.Listing.WithPhotos)
{
/***** Show student's photo *****/
HTM_TD_Begin ("class=\"LM COLOR%u\"",Gbl.RowEvenOdd);
Pho_ShowUsrPhotoIfAllowed (UsrDat,"PHOTO21x28",Pho_NO_ZOOM,false);
if (Gbl.Usrs.Listing.WithPhotos)
{
/***** Show student's photo *****/
HTM_TD_Begin ("class=\"LM COLOR%u\"",Gbl.RowEvenOdd);
Pho_ShowUsrPhotoIfAllowed (UsrDat,"PHOTO21x28",Pho_NO_ZOOM,false);
HTM_TD_End ();
}
/****** Write user's ID ******/
HTM_TD_Begin ("class=\"%s LM COLOR%u\"",
UsrDat->Accepted ? "DAT_SMALL_N" :
"DAT_SMALL",
Gbl.RowEvenOdd);
ID_WriteUsrIDs (UsrDat,NULL);
HTM_NBSP ();
HTM_TD_End ();
}
/****** Write user's ID ******/
HTM_TD_Begin ("class=\"%s LM COLOR%u\"",
UsrDat->Accepted ? "DAT_SMALL_N" :
"DAT_SMALL",
Gbl.RowEvenOdd);
ID_WriteUsrIDs (UsrDat,NULL);
HTM_NBSP ();
HTM_TD_End ();
/***** Write rest of main student's data *****/
Ins.InsCod = UsrDat->InsCod;
Ins_GetDataOfInstitutionByCod (&Ins);
Usr_WriteMainUsrDataExceptUsrID (UsrDat,Gbl.ColorRows[Gbl.RowEvenOdd]);
Usr_WriteEmail (UsrDat,Gbl.ColorRows[Gbl.RowEvenOdd]);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
Ins.FullName,
NULL,true,UsrDat->Accepted);
/***** Write rest of main student's data *****/
Ins.InsCod = UsrDat->InsCod;
Ins_GetDataOfInstitutionByCod (&Ins);
Usr_WriteMainUsrDataExceptUsrID (UsrDat,Gbl.ColorRows[Gbl.RowEvenOdd]);
Usr_WriteEmail (UsrDat,Gbl.ColorRows[Gbl.RowEvenOdd]);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
Ins.FullName,
NULL,true,UsrDat->Accepted);
/***** Write the rest of the data of the student *****/
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
UsrDat->Phone[0][0] ? (ShowData ? UsrDat->Phone[0] :
"********") :
"&nbsp;",
NULL,true,UsrDat->Accepted);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
UsrDat->Phone[1][0] ? (ShowData ? UsrDat->Phone[1] :
"********") :
"&nbsp;",
NULL,true,UsrDat->Accepted);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
UsrDat->StrBirthday[0] ? (ShowData ? UsrDat->StrBirthday :
"********") :
"&nbsp;",
NULL,true,UsrDat->Accepted);
/***** Write the rest of the data of the student *****/
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
UsrDat->Phone[0][0] ? (ShowData ? UsrDat->Phone[0] :
"********") :
"&nbsp;",
NULL,true,UsrDat->Accepted);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
UsrDat->Phone[1][0] ? (ShowData ? UsrDat->Phone[1] :
"********") :
"&nbsp;",
NULL,true,UsrDat->Accepted);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],
UsrDat->StrBirthday[0] ? (ShowData ? UsrDat->StrBirthday :
"********") :
"&nbsp;",
NULL,true,UsrDat->Accepted);
if (Gbl.Scope.Current == HieLvl_CRS)
{
/***** Write the groups a the que pertenece the student *****/
for (NumGrpTyp = 0;
NumGrpTyp < Gbl.Crs.Grps.GrpTypes.Num;
NumGrpTyp++)
if (Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].NumGrps) // If current course tiene groups of este type
{
Grp_GetNamesGrpsUsrBelongsTo (UsrDat->UsrCod,
Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod,
GroupNames);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],GroupNames,NULL,true,UsrDat->Accepted);
}
if (Gbl.Scope.Current == HieLvl_CRS)
{
/***** Write the groups a the que pertenece the student *****/
for (NumGrpTyp = 0;
NumGrpTyp < Gbl.Crs.Grps.GrpTypes.Num;
NumGrpTyp++)
if (Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].NumGrps) // If current course tiene groups of este type
{
Grp_GetNamesGrpsStdBelongsTo (Gbl.Crs.Grps.GrpTypes.LstGrpTypes[NumGrpTyp].GrpTypCod,
UsrDat->UsrCod,GroupNames);
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],GroupNames,NULL,true,UsrDat->Accepted);
}
/***** Fields of the record dependientes of the course *****/
for (NumField = 0;
NumField < Gbl.Crs.Records.LstFields.Num;
NumField++)
{
/* Get the text of the field */
if (Rec_DB_GetFieldFromCrsRecord (&mysql_res,UsrDat->UsrCod,
Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod))
{
row = mysql_fetch_row (mysql_res);
Str_Copy (Text,row[0],sizeof (Text) - 1);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Text,Cns_MAX_BYTES_TEXT,false); // Se convierte of HTML a HTML respetuoso
}
else
Text[0] = '\0';
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],Text,NULL,false,UsrDat->Accepted);
/***** Fields of the record dependientes of the course *****/
for (NumField = 0;
NumField < Gbl.Crs.Records.LstFields.Num;
NumField++)
{
/* Get the text of the field */
if (Rec_DB_GetFieldFromCrsRecord (&mysql_res,UsrDat->UsrCod,
Gbl.Crs.Records.LstFields.Lst[NumField].FieldCod))
{
row = mysql_fetch_row (mysql_res);
Str_Copy (Text,row[0],sizeof (Text) - 1);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Text,Cns_MAX_BYTES_TEXT,false); // Se convierte of HTML a HTML respetuoso
}
else
Text[0] = '\0';
Usr_WriteUsrData (Gbl.ColorRows[Gbl.RowEvenOdd],Text,NULL,false,UsrDat->Accepted);
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
}
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
}
}
/***** End row *****/
HTM_TR_End ();