Version 20.75: May 11, 2021 New module swad_assignment_database for database queries related to assignments.

This commit is contained in:
acanas 2021-05-11 18:22:00 +02:00
parent 101c24381c
commit b30caef053
11 changed files with 992 additions and 690 deletions

View File

@ -29,7 +29,7 @@
OBJS = swad_account.o swad_account_database.o swad_action.o swad_agenda.o \
swad_agenda_database.o swad_alert.o swad_announcement.o \
swad_announcement_database.o swad_API.o swad_assignment.o \
swad_attendance.o \
swad_assignment_database.o swad_attendance.o \
swad_banner.o swad_box.o swad_building.o swad_button.o \
swad_calendar.o swad_call_for_exam.o swad_center.o \
swad_center_config.o swad_chat.o swad_config.o swad_connected.o \

View File

@ -30,7 +30,7 @@
#include "swad_account.h"
#include "swad_account_database.h"
#include "swad_agenda_database.h"
#include "swad_announcement.h"
#include "swad_announcement_database.h"
#include "swad_attendance.h"
#include "swad_box.h"
#include "swad_calendar.h"

View File

@ -582,7 +582,7 @@ const struct Act_Actions Act_Actions[Act_NUM_ACTIONS] =
[ActReqRemAsg ] = { 813,-1,TabUnk,ActSeeAsg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Asg_ReqRemAssignment ,NULL},
[ActRemAsg ] = { 806,-1,TabUnk,ActSeeAsg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Asg_RemoveAssignment ,NULL},
[ActHidAsg ] = { 964,-1,TabUnk,ActSeeAsg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Asg_HideAssignment ,NULL},
[ActShoAsg ] = { 965,-1,TabUnk,ActSeeAsg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Asg_ShowAssignment ,NULL},
[ActShoAsg ] = { 965,-1,TabUnk,ActSeeAsg ,0x220,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Asg_UnhideAssignment ,NULL},
[ActReqUsrPrj ] = {1805,-1,TabUnk,ActSeePrj ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_1ST_TAB,NULL ,Prj_ListUsrsToSelect ,NULL},
[ActSeeTblAllPrj ] = {1696,-1,TabUnk,ActSeePrj ,0x238,0x200, 0, 0, 0, 0, 0,Act_CONT_NORM,Act_BRW_NEW_TAB,NULL ,Prj_ShowTableSelectedPrjs ,NULL},

View File

@ -33,6 +33,7 @@
#include <string.h> // For string functions
#include "swad_assignment.h"
#include "swad_assignment_database.h"
#include "swad_box.h"
#include "swad_database.h"
#include "swad_error.h"
@ -93,14 +94,10 @@ static void Asg_GetDataOfAssignment (struct Asg_Assignment *Asg,
unsigned NumAsgs);
static void Asg_ResetAssignment (struct Asg_Assignment *Asg);
static void Asg_FreeListAssignments (struct Asg_Assignments *Assignments);
static void Asg_GetAssignmentTxtFromDB (long AsgCod,char Txt[Cns_MAX_BYTES_TEXT + 1]);
static void Asg_PutParamAsgCod (long AsgCod);
static bool Asg_CheckIfSimilarAssignmentExists (const char *Field,const char *Value,long AsgCod);
static void Asg_ShowLstGrpsToEditAssignment (long AsgCod);
static void Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,unsigned NumUsrsToBeNotifiedByEMail);
static void Asg_CreateAssignment (struct Asg_Assignment *Asg,const char *Txt);
static void Asg_UpdateAssignment (struct Asg_Assignment *Asg,const char *Txt);
static void Asg_RemoveAllTheGrpsAssociatedToAnAssignment (long AsgCod);
static void Asg_CreateGrps (long AsgCod);
static void Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (struct Asg_Assignment *Asg);
static bool Asg_CheckIfIBelongToCrsOrGrpsThisAssignment (long AsgCod);
@ -180,8 +177,10 @@ static void Asg_ShowAllAssignments (struct Asg_Assignments *Assignments)
if (Assignments->Num)
{
/***** Table head *****/
/***** Begin table *****/
HTM_TABLE_BeginWideMarginPadding (2);
/***** Table head *****/
Asg_PutHeadForSeeing (Assignments,false); // Not print view
/***** Write all the assignments *****/
@ -234,28 +233,39 @@ static void Asg_PutHeadForSeeing (struct Asg_Assignments *Assignments,
Order <= Dat_END_TIME;
Order++)
{
/* Begin head cell */
HTM_TH_Begin (1,1,"LM");
if (!PrintView)
{
/* Begin form */
Frm_BeginForm (ActSeeAsg);
WhichGroups = Grp_GetParamWhichGroups ();
Grp_PutParamWhichGroups (&WhichGroups);
Pag_PutHiddenParamPagNum (Pag_ASSIGNMENTS,Assignments->CurrentPage);
Dat_PutHiddenParamOrder (Order);
/* Begin link to select order */
HTM_BUTTON_SUBMIT_Begin (Txt_START_END_TIME_HELP[Order],"BT_LINK TIT_TBL",NULL);
if (Order == Assignments->SelectedOrder)
HTM_U_Begin ();
}
/* Start / end text */
HTM_Txt (Txt_START_END_TIME[Order]);
if (!PrintView)
{
/* End link to select order */
if (Order == Assignments->SelectedOrder)
HTM_U_End ();
HTM_BUTTON_End ();
/* End form */
Frm_EndForm ();
}
/* End head cell */
HTM_TH_End ();
}
HTM_TH (1,1,"LM",Txt_Assignment);
@ -317,11 +327,15 @@ static void Asg_PutButtonToCreateNewAsg (void *Assignments)
if (Assignments)
{
((struct Asg_Assignments *) Assignments)->AsgCodToEdit = -1L;
/* Begin form */
Frm_BeginForm (ActFrmNewAsg);
((struct Asg_Assignments *) Assignments)->AsgCodToEdit = -1L;
Asg_PutParams (Assignments);
/* Button to create new assignment */
Btn_PutConfirmButton (Txt_New_assignment);
/* End form */
Frm_EndForm ();
}
}
@ -361,8 +375,10 @@ void Asg_PrintOneAssignment (void)
Gbl.Hierarchy.Deg.DegCod,
Gbl.Hierarchy.Crs.CrsCod);
/***** Table head *****/
/***** Begin table *****/
HTM_TABLE_BeginWideMarginPadding (2);
/***** Table head *****/
Asg_PutHeadForSeeing (&Assignments,
true); // Print view
@ -478,7 +494,7 @@ static void Asg_ShowOneAssignment (struct Asg_Assignments *Assignments,
HTM_TD_End ();
/* Text of the assignment */
Asg_GetAssignmentTxtFromDB (Asg.AsgCod,Txt);
Asg_DB_GetAssignmentTxtByCod (Asg.AsgCod,Txt);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
@ -488,10 +504,12 @@ static void Asg_ShowOneAssignment (struct Asg_Assignments *Assignments,
HTM_TD_Begin ("colspan=\"2\" class=\"LT COLOR%u\"",Gbl.RowEvenOdd);
if (Gbl.Crs.Grps.NumGrps)
Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (&Asg);
HTM_DIV_Begin ("class=\"PAR %s\"",Asg.Hidden ? "DAT_LIGHT" :
"DAT");
HTM_Txt (Txt);
HTM_DIV_End ();
HTM_TD_End ();
HTM_TR_End ();
@ -661,29 +679,11 @@ static void Asg_PutParams (void *Assignments)
}
/*****************************************************************************/
/************************ List all the assignments ***************************/
/*************************** List all assignments ****************************/
/*****************************************************************************/
static void Asg_GetListAssignments (struct Asg_Assignments *Assignments)
{
static const char *HiddenSubQuery[Rol_NUM_ROLES] =
{
[Rol_UNK ] = " AND Hidden='N'",
[Rol_GST ] = " AND Hidden='N'",
[Rol_USR ] = " AND Hidden='N'",
[Rol_STD ] = " AND Hidden='N'",
[Rol_NET ] = " AND Hidden='N'",
[Rol_TCH ] = "",
[Rol_DEG_ADM] = " AND Hidden='N'",
[Rol_CTR_ADM] = " AND Hidden='N'",
[Rol_INS_ADM] = " AND Hidden='N'",
[Rol_SYS_ADM] = "",
};
static const char *OrderBySubQuery[Dat_NUM_START_END_TIME] =
{
[Dat_START_TIME] = "StartTime DESC,EndTime DESC,Title DESC",
[Dat_END_TIME ] = "EndTime DESC,StartTime DESC,Title DESC",
};
MYSQL_RES *mysql_res;
unsigned NumAsgs;
unsigned NumAsg;
@ -693,40 +693,9 @@ static void Asg_GetListAssignments (struct Asg_Assignments *Assignments)
/***** Get list of assignments from database *****/
if (Gbl.Crs.Grps.WhichGrps == Grp_MY_GROUPS)
NumAsgs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get assignments",
"SELECT AsgCod"
" FROM asg_assignments"
" WHERE CrsCod=%ld%s"
" AND ("
// Assignment is for the whole course
"AsgCod NOT IN"
" (SELECT AsgCod"
" FROM asg_groups)" // Not associated to any group
" OR"
// Assignment is for some of my groups
" AsgCod IN"
" (SELECT asg_groups.AsgCod"
" FROM asg_groups,"
"grp_users"
" WHERE grp_users.UsrCod=%ld"
" AND asg_groups.GrpCod=grp_users.GrpCod)"
")"
" ORDER BY %s",
Gbl.Hierarchy.Crs.CrsCod,
HiddenSubQuery[Gbl.Usrs.Me.Role.Logged],
Gbl.Usrs.Me.UsrDat.UsrCod,
OrderBySubQuery[Assignments->SelectedOrder]);
NumAsgs = Asg_DB_GetListAssignmentsMyGrps (&mysql_res,Assignments->SelectedOrder);
else // Gbl.Crs.Grps.WhichGrps == Grp_ALL_GROUPS
NumAsgs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get assignments",
"SELECT AsgCod"
" FROM asg_assignments"
" WHERE CrsCod=%ld%s"
" ORDER BY %s",
Gbl.Hierarchy.Crs.CrsCod,
HiddenSubQuery[Gbl.Usrs.Me.Role.Logged],
OrderBySubQuery[Assignments->SelectedOrder]);
NumAsgs = Asg_DB_GetListAssignmentsAllGrps (&mysql_res,Assignments->SelectedOrder);
if (NumAsgs) // Assignments found...
{
@ -741,12 +710,10 @@ static void Asg_GetListAssignments (struct Asg_Assignments *Assignments)
for (NumAsg = 0;
NumAsg < Assignments->Num;
NumAsg++)
{
/* Get next assignment code */
if ((Assignments->LstAsgCods[NumAsg] = DB_GetNextCode (mysql_res)) <= 0)
Err_WrongAssignmentExit ();
}
}
else
Assignments->Num = 0;
@ -768,21 +735,7 @@ void Asg_GetDataOfAssignmentByCod (struct Asg_Assignment *Asg)
if (Asg->AsgCod > 0)
{
/***** Build query *****/
NumAsgs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get assignment data",
"SELECT AsgCod," // row[0]
"Hidden," // row[1]
"UsrCod," // row[2]
"UNIX_TIMESTAMP(StartTime)," // row[3]
"UNIX_TIMESTAMP(EndTime)," // row[4]
"NOW() BETWEEN StartTime AND EndTime," // row[5]
"Title," // row[6]
"Folder" // row[7]
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
Asg->AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
NumAsgs = Asg_DB_GetDataOfAssignmentByCod (&mysql_res,Asg->AsgCod);
/***** Get data of assignment *****/
Asg_GetDataOfAssignment (Asg,&mysql_res,NumAsgs);
@ -807,21 +760,7 @@ void Asg_GetDataOfAssignmentByFolder (struct Asg_Assignment *Asg)
if (Asg->Folder[0])
{
/***** Query database *****/
NumAsgs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get assignment data",
"SELECT AsgCod," // row[0]
"Hidden," // row[1]
"UsrCod," // row[2]
"UNIX_TIMESTAMP(StartTime)," // row[3]
"UNIX_TIMESTAMP(EndTime)," // row[4]
"NOW() BETWEEN StartTime AND EndTime," // row[5]
"Title," // row[6]
"Folder" // row[7]
" FROM asg_assignments"
" WHERE CrsCod=%ld"
" AND Folder='%s'",
Gbl.Hierarchy.Crs.CrsCod,
Asg->Folder);
NumAsgs = Asg_DB_GetDataOfAssignmentByFolder (&mysql_res,Asg->Folder);
/***** Get data of assignment *****/
Asg_GetDataOfAssignment (Asg,&mysql_res,NumAsgs);
@ -872,10 +811,8 @@ static void Asg_GetDataOfAssignment (struct Asg_Assignment *Asg,
/* Get author of the assignment (row[2]) */
Asg->UsrCod = Str_ConvertStrCodToLongCod (row[2]);
/* Get start date (row[3] holds the start UTC time) */
/* Get start and end dates (row[3] and row[4] hold the start UTC time) */
Asg->TimeUTC[Dat_START_TIME] = Dat_GetUNIXTimeFromStr (row[3]);
/* Get end date (row[4] holds the end UTC time) */
Asg->TimeUTC[Dat_END_TIME ] = Dat_GetUNIXTimeFromStr (row[4]);
/* Get whether the assignment is open or closed (row(5)) */
@ -931,22 +868,6 @@ static void Asg_FreeListAssignments (struct Asg_Assignments *Assignments)
}
}
/*****************************************************************************/
/******************** Get assignment text from database **********************/
/*****************************************************************************/
static void Asg_GetAssignmentTxtFromDB (long AsgCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
/***** Get text of assignment from database *****/
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get assignment text",
"SELECT Txt" // row[0]
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/***************** Get summary and content of an assignment *****************/
/*****************************************************************************/
@ -958,22 +879,12 @@ void Asg_GetNotifAssignment (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumAsgs;
size_t Length;
SummaryStr[0] = '\0'; // Return nothing on error
/***** Build query *****/
NumAsgs = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get assignment title and text",
"SELECT Title," // row[0]
"Txt" // row[1]
" FROM asg_assignments"
" WHERE AsgCod=%ld",
AsgCod);
/***** Result should have a unique row *****/
if (NumAsgs == 1)
/***** Query database. Result should have a unique row *****/
if (Asg_DB_GetAssignmentTitleAndTxtByCod (&mysql_res,AsgCod) == 1)
{
/***** Get row *****/
row = mysql_fetch_row (mysql_res);
@ -1082,15 +993,10 @@ void Asg_RemoveAssignment (void)
Brw_RemoveFoldersAssignmentsIfExistForAllUsrs (Asg.Folder);
/***** Remove all the groups of this assignment *****/
Asg_RemoveAllTheGrpsAssociatedToAnAssignment (Asg.AsgCod);
Asg_DB_RemoveAllGrpsAssociatedToAnAssignment (Asg.AsgCod);
/***** Remove assignment *****/
DB_QueryDELETE ("can not remove assignment",
"DELETE FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
Asg.AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
Asg_DB_RemoveAssignment (Asg.AsgCod);
/***** Mark possible notifications as removed *****/
Ntf_MarkNotifAsRemoved (Ntf_EVENT_ASSIGNMENT,Asg.AsgCod);
@ -1128,23 +1034,17 @@ void Asg_HideAssignment (void)
Asg_GetDataOfAssignmentByCod (&Asg);
/***** Hide assignment *****/
DB_QueryUPDATE ("can not hide assignment",
"UPDATE asg_assignments"
" SET Hidden='Y'"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
Asg.AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
Asg_DB_HideAssignment (Asg.AsgCod);
/***** Show all assignments again *****/
Asg_ShowAllAssignments (&Assignments);
}
/*****************************************************************************/
/**************************** Show an assignment *****************************/
/**************************** Unhide an assignment ***************************/
/*****************************************************************************/
void Asg_ShowAssignment (void)
void Asg_UnhideAssignment (void)
{
struct Asg_Assignments Assignments;
struct Asg_Assignment Asg;
@ -1164,36 +1064,13 @@ void Asg_ShowAssignment (void)
/***** Get data of the assignment from database *****/
Asg_GetDataOfAssignmentByCod (&Asg);
/***** Hide assignment *****/
DB_QueryUPDATE ("can not show assignment",
"UPDATE asg_assignments"
" SET Hidden='N'"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
Asg.AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
/***** Unhide assignment *****/
Asg_DB_UnhideAssignment (Asg.AsgCod);
/***** Show all assignments again *****/
Asg_ShowAllAssignments (&Assignments);
}
/*****************************************************************************/
/******** Check if the title or the folder of an assignment exists ***********/
/*****************************************************************************/
static bool Asg_CheckIfSimilarAssignmentExists (const char *Field,const char *Value,long AsgCod)
{
/***** Get number of assignments with a field value from database *****/
return (DB_QueryCOUNT ("can not get similar assignments",
"SELECT COUNT(*)"
" FROM asg_assignments"
" WHERE CrsCod=%ld"
" AND %s='%s'"
" AND AsgCod<>%ld",
Gbl.Hierarchy.Crs.CrsCod,
Field,Value,AsgCod) != 0);
}
/*****************************************************************************/
/****************** Put a form to create a new assignment ********************/
/*****************************************************************************/
@ -1255,7 +1132,7 @@ void Asg_RequestCreatOrEditAsg (void)
Asg_GetDataOfAssignmentByCod (&Asg);
/* Get text of the assignment from database */
Asg_GetAssignmentTxtFromDB (Asg.AsgCod,Txt);
Asg_DB_GetAssignmentTxtByCod (Asg.AsgCod,Txt);
}
/***** Begin form *****/
@ -1382,13 +1259,13 @@ static void Asg_ShowLstGrpsToEditAssignment (long AsgCod)
HTM_TD_End ();
HTM_TD_Begin ("class=\"LT\"");
Box_BoxTableBegin ("100%",NULL,
NULL,NULL,
Hlp_USERS_Groups,Box_NOT_CLOSABLE,0);
/***** First row: checkbox to select the whole course *****/
HTM_TR_Begin (NULL);
HTM_TD_Begin ("colspan=\"7\" class=\"DAT LM\"");
HTM_LABEL_Begin (NULL);
HTM_INPUT_CHECKBOX ("WholeCrs",HTM_DONT_SUBMIT_ON_CHANGE,
@ -1399,7 +1276,6 @@ static void Asg_ShowLstGrpsToEditAssignment (long AsgCod)
HTM_TxtF ("%s&nbsp;%s",Txt_The_whole_course,Gbl.Hierarchy.Crs.ShrtName);
HTM_LABEL_End ();
HTM_TD_End ();
HTM_TR_End ();
/***** List the groups for each group type *****/
@ -1412,6 +1288,7 @@ static void Asg_ShowLstGrpsToEditAssignment (long AsgCod)
/***** End table and box *****/
Box_BoxTableEnd ();
HTM_TD_End ();
HTM_TR_End ();
@ -1491,7 +1368,7 @@ void Asg_ReceiveFormAssignment (void)
if (NewAsg.Title[0]) // If there's an assignment title
{
/* If title of assignment was in database... */
if (Asg_CheckIfSimilarAssignmentExists ("Title",NewAsg.Title,NewAsg.AsgCod))
if (Asg_DB_CheckIfSimilarAssignmentExists ("Title",NewAsg.Title,NewAsg.AsgCod))
{
NewAssignmentIsCorrect = false;
@ -1504,7 +1381,7 @@ void Asg_ReceiveFormAssignment (void)
{
if (Str_ConvertFilFolLnkNameToValid (NewAsg.Folder)) // If folder name is valid...
{
if (Asg_CheckIfSimilarAssignmentExists ("Folder",NewAsg.Folder,NewAsg.AsgCod)) // If folder of assignment was in database...
if (Asg_DB_CheckIfSimilarAssignmentExists ("Folder",NewAsg.Folder,NewAsg.AsgCod)) // If folder of assignment was in database...
{
NewAssignmentIsCorrect = false;
@ -1570,7 +1447,8 @@ void Asg_ReceiveFormAssignment (void)
/***** Notify by email about the new assignment *****/
if ((NumUsrsToBeNotifiedByEMail = Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_ASSIGNMENT,NewAsg.AsgCod)))
Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (NewAsg.AsgCod,NumUsrsToBeNotifiedByEMail);
Asg_DB_UpdateNumUsrsNotifiedByEMailAboutAssignment (NewAsg.AsgCod,
NumUsrsToBeNotifiedByEMail);
/***** Show all assignments again *****/
Asg_ShowAllAssignments (&Assignments);
@ -1580,21 +1458,6 @@ void Asg_ReceiveFormAssignment (void)
Asg_RequestCreatOrEditAsg ();
}
/*****************************************************************************/
/******** Update number of users notified in table of assignments ************/
/*****************************************************************************/
static void Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,unsigned NumUsrsToBeNotifiedByEMail)
{
/***** Update number of users notified *****/
DB_QueryUPDATE ("can not update the number of notifs. of an assignment",
"UPDATE asg_assignments"
" SET NumNotif=NumNotif+%u"
" WHERE AsgCod=%ld",
NumUsrsToBeNotifiedByEMail,
AsgCod);
}
/*****************************************************************************/
/************************ Create a new assignment ****************************/
/*****************************************************************************/
@ -1602,23 +1465,7 @@ static void Asg_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,unsigne
static void Asg_CreateAssignment (struct Asg_Assignment *Asg,const char *Txt)
{
/***** Create a new assignment *****/
Asg->AsgCod =
DB_QueryINSERTandReturnCode ("can not create new assignment",
"INSERT INTO asg_assignments"
" (CrsCod,UsrCod,"
"StartTime,EndTime,"
"Title,Folder,Txt)"
" VALUES"
" (%ld,%ld,"
"FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld),"
"'%s','%s','%s')",
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Asg->TimeUTC[Dat_START_TIME],
Asg->TimeUTC[Dat_END_TIME ],
Asg->Title,
Asg->Folder,
Txt);
Asg->AsgCod = Asg_DB_CreateAssignment (Asg,Txt);
/***** Create groups *****/
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
@ -1632,76 +1479,17 @@ static void Asg_CreateAssignment (struct Asg_Assignment *Asg,const char *Txt)
static void Asg_UpdateAssignment (struct Asg_Assignment *Asg,const char *Txt)
{
/***** Update the data of the assignment *****/
DB_QueryUPDATE ("can not update assignment",
"UPDATE asg_assignments"
" SET StartTime=FROM_UNIXTIME(%ld),"
"EndTime=FROM_UNIXTIME(%ld),"
"Title='%s',"
"Folder='%s',"
"Txt='%s'"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
Asg->TimeUTC[Dat_START_TIME],
Asg->TimeUTC[Dat_END_TIME ],
Asg->Title,
Asg->Folder,
Txt,
Asg->AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
Asg_DB_UpdateAssignment (Asg,Txt);
/***** Update groups *****/
/* Remove old groups */
Asg_RemoveAllTheGrpsAssociatedToAnAssignment (Asg->AsgCod);
Asg_DB_RemoveAllGrpsAssociatedToAnAssignment (Asg->AsgCod);
/* Create new groups */
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
Asg_CreateGrps (Asg->AsgCod);
}
/*****************************************************************************/
/********************* Remove groups of an assignment ************************/
/*****************************************************************************/
static void Asg_RemoveAllTheGrpsAssociatedToAnAssignment (long AsgCod)
{
/***** Remove groups of the assignment *****/
DB_QueryDELETE ("can not remove the groups associated to an assignment",
"DELETE FROM asg_groups"
" WHERE AsgCod=%ld",
AsgCod);
}
/*****************************************************************************/
/**************** Remove one group from all the assignments ******************/
/*****************************************************************************/
void Asg_RemoveGroup (long GrpCod)
{
/***** Remove group from all the assignments *****/
DB_QueryDELETE ("can not remove group from the associations"
" between assignments and groups",
"DELETE FROM asg_groups"
" WHERE GrpCod=%ld",
GrpCod);
}
/*****************************************************************************/
/*********** Remove groups of one type from all the assignments **************/
/*****************************************************************************/
void Asg_RemoveGroupsOfType (long GrpTypCod)
{
/***** Remove group from all the assignments *****/
DB_QueryDELETE ("can not remove groups of a type from the associations"
" between assignments and groups",
"DELETE FROM asg_groups"
" USING grp_groups,"
"asg_groups"
" WHERE grp_groups.GrpTypCod=%ld"
" AND grp_groups.GrpCod=asg_groups.GrpCod",
GrpTypCod);
}
/*****************************************************************************/
/********************* Create groups of an assignment ************************/
/*****************************************************************************/
@ -1714,14 +1502,7 @@ static void Asg_CreateGrps (long AsgCod)
for (NumGrpSel = 0;
NumGrpSel < Gbl.Crs.Grps.LstGrpsSel.NumGrps;
NumGrpSel++)
/* Create group */
DB_QueryINSERT ("can not associate a group to an assignment",
"INSERT INTO asg_groups"
" (AsgCod,GrpCod)"
" VALUES"
" (%ld,%ld)",
AsgCod,
Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel]);
Asg_DB_CreateGrp (AsgCod,Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrpSel]);
}
/*****************************************************************************/
@ -1740,29 +1521,17 @@ static void Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (struct Asg_Assignment *As
unsigned NumGrp;
/***** Get groups associated to an assignment from database *****/
NumGrps = (unsigned)
DB_QuerySELECT (&mysql_res,"can not get groups of an assignment",
"SELECT grp_types.GrpTypName," // row[0]
"grp_groups.GrpName" // row[1]
" FROM asg_groups,"
"grp_groups,"
"grp_types"
" WHERE asg_groups.AsgCod=%ld"
" AND asg_groups.GrpCod=grp_groups.GrpCod"
" AND grp_groups.GrpTypCod=grp_types.GrpTypCod"
" ORDER BY grp_types.GrpTypName,"
"grp_groups.GrpName",
Asg->AsgCod);
NumGrps = Asg_DB_GetGrps (&mysql_res,Asg->AsgCod);
/***** Write heading *****/
HTM_DIV_Begin ("class=\"%s\"",Asg->Hidden ? "ASG_GRP_LIGHT" :
"ASG_GRP");
HTM_TxtColonNBSP (NumGrps == 1 ? Txt_Group :
Txt_Groups);
/***** Write groups *****/
if (NumGrps) // Groups found...
{
/* Get and write the group types and names */
for (NumGrp = 0;
NumGrp < NumGrps;
@ -1783,7 +1552,6 @@ static void Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (struct Asg_Assignment *As
HTM_Txt (", ");
}
}
}
else
HTM_TxtF ("%s&nbsp;%s",Txt_The_whole_course,Gbl.Hierarchy.Crs.ShrtName);
@ -1799,20 +1567,11 @@ static void Asg_GetAndWriteNamesOfGrpsAssociatedToAsg (struct Asg_Assignment *As
void Asg_RemoveCrsAssignments (long CrsCod)
{
/***** Remove groups *****/
DB_QueryDELETE ("can not remove groups associated to assignments in a course",
"DELETE FROM asg_groups"
" USING asg_assignments,"
"asg_groups"
" WHERE asg_assignments.CrsCod=%ld"
" AND asg_assignments.AsgCod=asg_groups.AsgCod",
CrsCod);
/***** Remove groups associated to assignments in course *****/
Asg_DB_RemoveGrpsAssociatedToAsgsInCrs (CrsCod);
/***** Remove assignments *****/
DB_QueryDELETE ("can not remove all assignments in a course",
"DELETE FROM asg_assignments"
" WHERE CrsCod=%ld",
CrsCod);
Asg_DB_RemoveCrsAssignments (CrsCod);
}
/*****************************************************************************/
@ -1828,25 +1587,7 @@ static bool Asg_CheckIfIBelongToCrsOrGrpsThisAssignment (long AsgCod)
case Rol_TCH:
// Students and teachers can do assignments depending on groups
/***** Get if I can do an assignment from database *****/
return (DB_QueryCOUNT ("can not check if I can do an assignment",
"SELECT COUNT(*)"
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND ("
// Assignment is for the whole course
"AsgCod NOT IN"
" (SELECT AsgCod"
" FROM asg_groups)"
" OR "
// Assignment is for some of my groups
"AsgCod IN"
" (SELECT asg_groups.AsgCod"
" FROM grp_users,"
"asg_groups"
" WHERE grp_users.UsrCod=%ld"
" AND asg_groups.GrpCod=grp_users.GrpCod)"
")",
AsgCod,Gbl.Usrs.Me.UsrDat.UsrCod) != 0);
return Asg_DB_CheckIfICanDoAssignment (AsgCod);
case Rol_SYS_ADM:
return true;
default:
@ -1854,84 +1595,6 @@ static bool Asg_CheckIfIBelongToCrsOrGrpsThisAssignment (long AsgCod)
}
}
/*****************************************************************************/
/****************** Get number of courses with assignments *******************/
/*****************************************************************************/
// Returns the number of courses with assignments
// in this location (all the platform, current degree or current course)
unsigned Asg_GetNumCoursesWithAssignments (Hie_Lvl_Level_t Scope)
{
/***** Get number of courses with assignments from database *****/
switch (Scope)
{
case Hie_Lvl_SYS:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT CrsCod)"
" FROM asg_assignments"
" WHERE CrsCod>0");
case Hie_Lvl_CTY:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM ins_instits,"
"ctr_centers,"
"deg_degrees,"
"courses,"
"asg_assignments"
" WHERE ins_instits.CtyCod=%ld"
" AND ins_instits.InsCod=ctr_centers.InsCod"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Cty.CtyCod);
case Hie_Lvl_INS:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM ctr_centers,"
"deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE ctr_centers.InsCod=%ld"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ins.InsCod);
case Hie_Lvl_CTR:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE deg_degrees.CtrCod=%ld"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ctr.CtrCod);
case Hie_Lvl_DEG:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM crs_courses,"
"asg_assignments"
" WHERE crs_courses.DegCod=%ld"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Deg.DegCod);
case Hie_Lvl_CRS:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT CrsCod)"
" FROM asg_assignments"
" WHERE CrsCod=%ld",
Gbl.Hierarchy.Crs.CrsCod);
default:
Err_WrongScopeExit ();
return 0;
}
}
/*****************************************************************************/
/************************ Get number of assignments **************************/
/*****************************************************************************/
@ -1944,81 +1607,13 @@ unsigned Asg_GetNumAssignments (Hie_Lvl_Level_t Scope,unsigned *NumNotif)
MYSQL_ROW row;
unsigned NumAssignments;
/***** Get number of assignments from database *****/
switch (Scope)
{
case Hie_Lvl_SYS:
DB_QuerySELECT (&mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(NumNotif)" // row[1]
" FROM asg_assignments"
" WHERE CrsCod>0");
break;
case Hie_Lvl_CTY:
DB_QuerySELECT (&mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM ins_instits,"
"ctr_centers,"
"deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE ins_instits.CtyCod=%ld"
" AND ins_instits.InsCod=ctr_centers.InsCod"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Cty.CtyCod);
break;
case Hie_Lvl_INS:
DB_QuerySELECT (&mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM ctr_centers,"
"deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE ctr_centers.InsCod=%ld"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ins.InsCod);
break;
case Hie_Lvl_CTR:
DB_QuerySELECT (&mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE deg_degrees.CtrCod=%ld"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ctr.CtrCod);
break;
case Hie_Lvl_DEG:
DB_QuerySELECT (&mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM crs_courses,"
"asg_assignments"
" WHERE crs_courses.DegCod=%ld"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Deg.DegCod);
break;
case Hie_Lvl_CRS:
DB_QuerySELECT (&mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(NumNotif)" // row[1]
" FROM asg_assignments"
" WHERE CrsCod=%ld",
Gbl.Hierarchy.Crs.CrsCod);
break;
default:
Err_WrongScopeExit ();
break;
}
/***** Default values *****/
NumAssignments = 0;
*NumNotif = 0;
/***** Get number of assignments from database *****/
if (Asg_DB_GetNumAssignments (&mysql_res,Scope))
{
/***** Get number of assignments *****/
row = mysql_fetch_row (mysql_res);
if (sscanf (row[0],"%u",&NumAssignments) != 1)
@ -2026,30 +1621,12 @@ unsigned Asg_GetNumAssignments (Hie_Lvl_Level_t Scope,unsigned *NumNotif)
/***** Get number of notifications by email *****/
if (row[1])
{
if (sscanf (row[1],"%u",NumNotif) != 1)
Err_ShowErrorAndExit ("Error when getting number of notifications of assignments.");
}
else
*NumNotif = 0;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumAssignments;
}
/*****************************************************************************/
/****************** Get number of assignments in a course ********************/
/*****************************************************************************/
unsigned Asg_GetNumAssignmentsInCrs (long CrsCod)
{
/***** Get number of assignments in a course from database *****/
return (unsigned)
DB_QueryCOUNT ("can not get number of assignments in course",
"SELECT COUNT(*)"
" FROM asg_assignments"
" WHERE CrsCod=%ld",
CrsCod);
}

View File

@ -94,14 +94,10 @@ long Asg_GetParamAsgCod (void);
void Asg_ReqRemAssignment (void);
void Asg_RemoveAssignment (void);
void Asg_HideAssignment (void);
void Asg_ShowAssignment (void);
void Asg_UnhideAssignment (void);
void Asg_ReceiveFormAssignment (void);
void Asg_RemoveGroup (long GrpCod);
void Asg_RemoveGroupsOfType (long GrpTypCod);
void Asg_RemoveCrsAssignments (long CrsCod);
unsigned Asg_GetNumCoursesWithAssignments (Hie_Lvl_Level_t Scope);
unsigned Asg_GetNumAssignments (Hie_Lvl_Level_t Scope,unsigned *NumNotif);
unsigned Asg_GetNumAssignmentsInCrs (long CrsCod);
#endif

640
swad_assignment_database.c Normal file
View File

@ -0,0 +1,640 @@
// swad_assignment_database.c: assignments operations with database
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2021 Antonio Cañas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include "swad_assignment.h"
#include "swad_assignment_database.h"
#include "swad_database.h"
#include "swad_date.h"
#include "swad_error.h"
#include "swad_global.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
static const char *Asg_DB_HiddenSubQuery[Rol_NUM_ROLES] =
{
[Rol_UNK ] = " AND Hidden='N'",
[Rol_GST ] = " AND Hidden='N'",
[Rol_USR ] = " AND Hidden='N'",
[Rol_STD ] = " AND Hidden='N'",
[Rol_NET ] = " AND Hidden='N'",
[Rol_TCH ] = "",
[Rol_DEG_ADM] = " AND Hidden='N'",
[Rol_CTR_ADM] = " AND Hidden='N'",
[Rol_INS_ADM] = " AND Hidden='N'",
[Rol_SYS_ADM] = "",
};
static const char *Asg_DB_OrderSubQuery[Dat_NUM_START_END_TIME] =
{
[Dat_START_TIME] = "StartTime DESC,"
"EndTime DESC,"
"Title DESC",
[Dat_END_TIME ] = "EndTime DESC,"
"StartTime DESC,"
"Title DESC",
};
/*****************************************************************************/
/***************************** Private variables *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************* Get list of assignments for my groups *******************/
/*****************************************************************************/
unsigned Asg_DB_GetListAssignmentsMyGrps (MYSQL_RES **mysql_res,
Dat_StartEndTime_t SelectedOrder)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get assignments",
"SELECT AsgCod"
" FROM asg_assignments"
" WHERE CrsCod=%ld%s"
" AND ("
// Assignment is for the whole course
"AsgCod NOT IN"
" (SELECT AsgCod"
" FROM asg_groups)" // Not associated to any group
" OR"
// Assignment is for some of my groups
" AsgCod IN"
" (SELECT asg_groups.AsgCod"
" FROM asg_groups,"
"grp_users"
" WHERE grp_users.UsrCod=%ld"
" AND asg_groups.GrpCod=grp_users.GrpCod)"
")"
" ORDER BY %s",
Gbl.Hierarchy.Crs.CrsCod,
Asg_DB_HiddenSubQuery[Gbl.Usrs.Me.Role.Logged],
Gbl.Usrs.Me.UsrDat.UsrCod,
Asg_DB_OrderSubQuery[SelectedOrder]);
}
/*****************************************************************************/
/****************** Get list of assignments for all groups *******************/
/*****************************************************************************/
unsigned Asg_DB_GetListAssignmentsAllGrps (MYSQL_RES **mysql_res,
Dat_StartEndTime_t SelectedOrder)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get assignments",
"SELECT AsgCod"
" FROM asg_assignments"
" WHERE CrsCod=%ld%s"
" ORDER BY %s",
Gbl.Hierarchy.Crs.CrsCod,
Asg_DB_HiddenSubQuery[Gbl.Usrs.Me.Role.Logged],
Asg_DB_OrderSubQuery[SelectedOrder]);
}
/*****************************************************************************/
/******************* Get assignment data using its code **********************/
/*****************************************************************************/
unsigned Asg_DB_GetDataOfAssignmentByCod (MYSQL_RES **mysql_res,long AsgCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get assignment data",
"SELECT AsgCod," // row[0]
"Hidden," // row[1]
"UsrCod," // row[2]
"UNIX_TIMESTAMP(StartTime)," // row[3]
"UNIX_TIMESTAMP(EndTime)," // row[4]
"NOW() BETWEEN StartTime AND EndTime," // row[5]
"Title," // row[6]
"Folder" // row[7]
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld", // Extra check
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/**************** Get assignment data using its folder name ******************/
/*****************************************************************************/
unsigned Asg_DB_GetDataOfAssignmentByFolder (MYSQL_RES **mysql_res,
const char Folder[Brw_MAX_BYTES_FOLDER + 1])
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get assignment data",
"SELECT AsgCod," // row[0]
"Hidden," // row[1]
"UsrCod," // row[2]
"UNIX_TIMESTAMP(StartTime)," // row[3]
"UNIX_TIMESTAMP(EndTime)," // row[4]
"NOW() BETWEEN StartTime AND EndTime," // row[5]
"Title," // row[6]
"Folder" // row[7]
" FROM asg_assignments"
" WHERE CrsCod=%ld" // Extra check
" AND Folder='%s'",
Gbl.Hierarchy.Crs.CrsCod,
Folder);
}
/*****************************************************************************/
/************* Get title and text of assignment using its code ***************/
/*****************************************************************************/
unsigned Asg_DB_GetAssignmentTitleAndTxtByCod (MYSQL_RES **mysql_res,long AsgCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get assignment title and text",
"SELECT Title," // row[0]
"Txt" // row[1]
" FROM asg_assignments"
" WHERE AsgCod=%ld",
AsgCod);
}
/*****************************************************************************/
/******************** Get assignment text from database **********************/
/*****************************************************************************/
void Asg_DB_GetAssignmentTxtByCod (long AsgCod,char Txt[Cns_MAX_BYTES_TEXT + 1])
{
DB_QuerySELECTString (Txt,Cns_MAX_BYTES_TEXT,"can not get assignment text",
"SELECT Txt"
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld", // Extra check
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/******** Check if the title or the folder of an assignment exists ***********/
/*****************************************************************************/
bool Asg_DB_CheckIfSimilarAssignmentExists (const char *Field,const char *Value,
long AsgCod)
{
/***** Get number of assignments with a field value from database *****/
return (DB_QueryCOUNT ("can not get similar assignments",
"SELECT COUNT(*)"
" FROM asg_assignments"
" WHERE CrsCod=%ld"
" AND %s='%s'"
" AND AsgCod<>%ld",
Gbl.Hierarchy.Crs.CrsCod,
Field,Value,AsgCod) != 0);
}
/*****************************************************************************/
/************************ Create a new assignment ****************************/
/*****************************************************************************/
long Asg_DB_CreateAssignment (const struct Asg_Assignment *Asg,const char *Txt)
{
return
DB_QueryINSERTandReturnCode ("can not create new assignment",
"INSERT INTO asg_assignments"
" (CrsCod,UsrCod,"
"StartTime,EndTime,"
"Title,Folder,Txt)"
" VALUES"
" (%ld,%ld,"
"FROM_UNIXTIME(%ld),FROM_UNIXTIME(%ld),"
"'%s','%s','%s')",
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Asg->TimeUTC[Dat_START_TIME],
Asg->TimeUTC[Dat_END_TIME ],
Asg->Title,
Asg->Folder,
Txt);
}
/*****************************************************************************/
/********************* Update an existing assignment *************************/
/*****************************************************************************/
void Asg_DB_UpdateAssignment (const struct Asg_Assignment *Asg,const char *Txt)
{
/***** Update the data of the assignment *****/
DB_QueryUPDATE ("can not update assignment",
"UPDATE asg_assignments"
" SET StartTime=FROM_UNIXTIME(%ld),"
"EndTime=FROM_UNIXTIME(%ld),"
"Title='%s',"
"Folder='%s',"
"Txt='%s'"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld", // Extra check
Asg->TimeUTC[Dat_START_TIME],
Asg->TimeUTC[Dat_END_TIME ],
Asg->Title,
Asg->Folder,
Txt,
Asg->AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/************************** Hide/unhide an assignment ************************/
/*****************************************************************************/
void Asg_DB_HideAssignment (long AsgCod)
{
DB_QueryUPDATE ("can not hide assignment",
"UPDATE asg_assignments"
" SET Hidden='Y'"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld", // Extra check
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
void Asg_DB_UnhideAssignment (long AsgCod)
{
DB_QueryUPDATE ("can not unhide assignment",
"UPDATE asg_assignments"
" SET Hidden='N'"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld",
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/**************************** Remove an assignment ***************************/
/*****************************************************************************/
void Asg_DB_RemoveAssignment (long AsgCod)
{
DB_QueryDELETE ("can not remove assignment",
"DELETE FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND CrsCod=%ld", // Extra check
AsgCod,
Gbl.Hierarchy.Crs.CrsCod);
}
/*****************************************************************************/
/******************* Get groups associated to an assignment ******************/
/*****************************************************************************/
bool Asg_DB_CheckIfICanDoAssignment (long AsgCod)
{
// Students and teachers can do assignments depending on groups
/***** Get if I can do an assignment from database *****/
return (DB_QueryCOUNT ("can not check if I can do an assignment",
"SELECT COUNT(*)"
" FROM asg_assignments"
" WHERE AsgCod=%ld"
" AND ("
// Assignment is for the whole course
"AsgCod NOT IN"
" (SELECT AsgCod"
" FROM asg_groups)"
" OR "
// Assignment is for some of my groups
"AsgCod IN"
" (SELECT asg_groups.AsgCod"
" FROM grp_users,"
"asg_groups"
" WHERE grp_users.UsrCod=%ld"
" AND asg_groups.GrpCod=grp_users.GrpCod)"
")",
AsgCod,
Gbl.Usrs.Me.UsrDat.UsrCod) != 0);
}
/*****************************************************************************/
/******************* Get groups associated to an assignment ******************/
/*****************************************************************************/
unsigned Asg_DB_GetGrps (MYSQL_RES **mysql_res,long AsgCod)
{
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get groups of an assignment",
"SELECT grp_types.GrpTypName," // row[0]
"grp_groups.GrpName" // row[1]
" FROM asg_groups,"
"grp_groups,"
"grp_types"
" WHERE asg_groups.AsgCod=%ld"
" AND asg_groups.GrpCod=grp_groups.GrpCod"
" AND grp_groups.GrpTypCod=grp_types.GrpTypCod"
" ORDER BY grp_types.GrpTypName,"
"grp_groups.GrpName",
AsgCod);
}
/*****************************************************************************/
/********************* Create a group of an assignment ************************/
/*****************************************************************************/
void Asg_DB_CreateGrp (long AsgCod,long GrpCod)
{
DB_QueryINSERT ("can not associate a group to an assignment",
"INSERT INTO asg_groups"
" (AsgCod,GrpCod)"
" VALUES"
" (%ld,%ld)",
AsgCod,
GrpCod);
}
/*****************************************************************************/
/**************** Remove one group from all the assignments ******************/
/*****************************************************************************/
void Asg_DB_RemoveGroup (long GrpCod)
{
/***** Remove group from all the assignments *****/
DB_QueryDELETE ("can not remove group from the associations"
" between assignments and groups",
"DELETE FROM asg_groups"
" WHERE GrpCod=%ld",
GrpCod);
}
/*****************************************************************************/
/*********** Remove groups of one type from all the assignments **************/
/*****************************************************************************/
void Asg_DB_RemoveGroupsOfType (long GrpTypCod)
{
/***** Remove group from all the assignments *****/
DB_QueryDELETE ("can not remove groups of a type from the associations"
" between assignments and groups",
"DELETE FROM asg_groups"
" USING grp_groups,"
"asg_groups"
" WHERE grp_groups.GrpTypCod=%ld"
" AND grp_groups.GrpCod=asg_groups.GrpCod",
GrpTypCod);
}
/*****************************************************************************/
/********************* Remove groups of an assignment ************************/
/*****************************************************************************/
void Asg_DB_RemoveAllGrpsAssociatedToAnAssignment (long AsgCod)
{
/***** Remove groups of the assignment *****/
DB_QueryDELETE ("can not remove the groups associated to an assignment",
"DELETE FROM asg_groups"
" WHERE AsgCod=%ld",
AsgCod);
}
/*****************************************************************************/
/*********** Remove groups associated to assignments in a course *************/
/*****************************************************************************/
void Asg_DB_RemoveGrpsAssociatedToAsgsInCrs (long CrsCod)
{
DB_QueryDELETE ("can not remove groups associated to assignments in a course",
"DELETE FROM asg_groups"
" USING asg_assignments,"
"asg_groups"
" WHERE asg_assignments.CrsCod=%ld"
" AND asg_assignments.AsgCod=asg_groups.AsgCod",
CrsCod);
}
/*****************************************************************************/
/****************** Remove all the assignments in a course *******************/
/*****************************************************************************/
void Asg_DB_RemoveCrsAssignments (long CrsCod)
{
DB_QueryDELETE ("can not remove all assignments in a course",
"DELETE FROM asg_assignments"
" WHERE CrsCod=%ld",
CrsCod);
}
/*****************************************************************************/
/******** Update number of users notified in table of assignments ************/
/*****************************************************************************/
void Asg_DB_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,
unsigned NumUsrsToBeNotifiedByEMail)
{
/***** Update number of users notified *****/
DB_QueryUPDATE ("can not update the number of notifs. of an assignment",
"UPDATE asg_assignments"
" SET NumNotif=NumNotif+%u"
" WHERE AsgCod=%ld",
NumUsrsToBeNotifiedByEMail,
AsgCod);
}
/*****************************************************************************/
/****************** Get number of courses with assignments *******************/
/*****************************************************************************/
// Returns the number of courses with assignments
// in this location (all the platform, current degree or current course)
unsigned Asg_DB_GetNumCoursesWithAssignments (Hie_Lvl_Level_t Scope)
{
/***** Get number of courses with assignments from database *****/
switch (Scope)
{
case Hie_Lvl_SYS:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT CrsCod)"
" FROM asg_assignments"
" WHERE CrsCod>0");
case Hie_Lvl_CTY:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM ins_instits,"
"ctr_centers,"
"deg_degrees,"
"courses,"
"asg_assignments"
" WHERE ins_instits.CtyCod=%ld"
" AND ins_instits.InsCod=ctr_centers.InsCod"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Cty.CtyCod);
case Hie_Lvl_INS:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM ctr_centers,"
"deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE ctr_centers.InsCod=%ld"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ins.InsCod);
case Hie_Lvl_CTR:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE deg_degrees.CtrCod=%ld"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ctr.CtrCod);
case Hie_Lvl_DEG:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT asg_assignments.CrsCod)"
" FROM crs_courses,"
"asg_assignments"
" WHERE crs_courses.DegCod=%ld"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Deg.DegCod);
case Hie_Lvl_CRS:
return (unsigned)
DB_QueryCOUNT ("can not get number of courses with assignments",
"SELECT COUNT(DISTINCT CrsCod)"
" FROM asg_assignments"
" WHERE CrsCod=%ld",
Gbl.Hierarchy.Crs.CrsCod);
default:
Err_WrongScopeExit ();
return 0;
}
}
/*****************************************************************************/
/************************ Get number of assignments **************************/
/*****************************************************************************/
// Returns the number of assignments
// in this location (all the platform, current degree or current course)
unsigned Asg_DB_GetNumAssignments (MYSQL_RES **mysql_res,Hie_Lvl_Level_t Scope)
{
/***** Get number of assignments from database *****/
switch (Scope)
{
case Hie_Lvl_SYS:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(NumNotif)" // row[1]
" FROM asg_assignments"
" WHERE CrsCod>0");
case Hie_Lvl_CTY:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM ins_instits,"
"ctr_centers,"
"deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE ins_instits.CtyCod=%ld"
" AND ins_instits.InsCod=ctr_centers.InsCod"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Cty.CtyCod);
case Hie_Lvl_INS:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM ctr_centers,"
"deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE ctr_centers.InsCod=%ld"
" AND ctr_centers.CtrCod=deg_degrees.CtrCod"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ins.InsCod);
case Hie_Lvl_CTR:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM deg_degrees,"
"crs_courses,"
"asg_assignments"
" WHERE deg_degrees.CtrCod=%ld"
" AND deg_degrees.DegCod=crs_courses.DegCod"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Ctr.CtrCod);
case Hie_Lvl_DEG:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(asg_assignments.NumNotif)" // row[1]
" FROM crs_courses,"
"asg_assignments"
" WHERE crs_courses.DegCod=%ld"
" AND crs_courses.CrsCod=asg_assignments.CrsCod",
Gbl.Hierarchy.Deg.DegCod);
case Hie_Lvl_CRS:
return (unsigned)
DB_QuerySELECT (mysql_res,"can not get number of assignments",
"SELECT COUNT(*)," // row[0]
"SUM(NumNotif)" // row[1]
" FROM asg_assignments"
" WHERE CrsCod=%ld",
Gbl.Hierarchy.Crs.CrsCod);
default:
Err_WrongScopeExit ();
return 0; // Not reached
}
}
/*****************************************************************************/
/****************** Get number of assignments in a course ********************/
/*****************************************************************************/
unsigned Asg_DB_GetNumAssignmentsInCrs (long CrsCod)
{
/***** Get number of assignments in a course from database *****/
return (unsigned)
DB_QueryCOUNT ("can not get number of assignments in course",
"SELECT COUNT(*)"
" FROM asg_assignments"
" WHERE CrsCod=%ld",
CrsCod);
}

View File

@ -0,0 +1,83 @@
// swad_assignment_database.h: assignments operations with database
#ifndef _SWAD_ASG_DB
#define _SWAD_ASG_DB
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2021 Antonio Cañas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include "swad_assignment.h"
#include "swad_database.h"
#include "swad_file_browser.h"
/*****************************************************************************/
/************************** Public types and constants ***********************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Public prototypes *****************************/
/*****************************************************************************/
unsigned Asg_DB_GetListAssignmentsMyGrps (MYSQL_RES **mysql_res,
Dat_StartEndTime_t SelectedOrder);
unsigned Asg_DB_GetListAssignmentsAllGrps (MYSQL_RES **mysql_res,
Dat_StartEndTime_t SelectedOrder);
unsigned Asg_DB_GetDataOfAssignmentByCod (MYSQL_RES **mysql_res,long AsgCod);
unsigned Asg_DB_GetDataOfAssignmentByFolder (MYSQL_RES **mysql_res,
const char Folder[Brw_MAX_BYTES_FOLDER + 1]);
unsigned Asg_DB_GetAssignmentTitleAndTxtByCod (MYSQL_RES **mysql_res,long AsgCod);
void Asg_DB_GetAssignmentTxtByCod (long AsgCod,char Txt[Cns_MAX_BYTES_TEXT + 1]);
bool Asg_DB_CheckIfSimilarAssignmentExists (const char *Field,const char *Value,
long AsgCod);
long Asg_DB_CreateAssignment (const struct Asg_Assignment *Asg,const char *Txt);
void Asg_DB_UpdateAssignment (const struct Asg_Assignment *Asg,const char *Txt);
void Asg_DB_HideAssignment (long AsgCod);
void Asg_DB_UnhideAssignment (long AsgCod);
void Asg_DB_RemoveAssignment (long AsgCod);
bool Asg_DB_CheckIfICanDoAssignment (long AsgCod);
unsigned Asg_DB_GetGrps (MYSQL_RES **mysql_res,long AsgCod);
void Asg_DB_CreateGrp (long AsgCod,long GrpCod);
void Asg_DB_RemoveGroup (long GrpCod);
void Asg_DB_RemoveGroupsOfType (long GrpTypCod);
void Asg_DB_RemoveAllGrpsAssociatedToAnAssignment (long AsgCod);
void Asg_DB_RemoveGrpsAssociatedToAsgsInCrs (long CrsCod);
void Asg_DB_RemoveCrsAssignments (long CrsCod);
void Asg_DB_UpdateNumUsrsNotifiedByEMailAboutAssignment (long AsgCod,
unsigned NumUsrsToBeNotifiedByEMail);
unsigned Asg_DB_GetNumCoursesWithAssignments (Hie_Lvl_Level_t Scope);
unsigned Asg_DB_GetNumAssignments (MYSQL_RES **mysql_res,Hie_Lvl_Level_t Scope);
unsigned Asg_DB_GetNumAssignmentsInCrs (long CrsCod);
#endif

View File

@ -599,15 +599,18 @@ TODO: BUG: Cuando un tipo de grupo s
TODO: Salvador Romero Cortés: @acanas opción para editar posts
TODO: FIX BUG, URGENT! En las fechas como parámetro Dat_WriteParamsIniEndDates(), por ejemplo al cambiar el color de la gráfica de accesos por día y hora, no se respeta la zona horaria.
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
*/
#define Log_PLATFORM_VERSION "SWAD 20.74 (2021-05-11)"
#define Log_PLATFORM_VERSION "SWAD 20.75 (2021-05-11)"
#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.74: May 11, 2021 New module swad_announcement_database for database queries related to announcements. (? lines)
Version 20.75: May 11, 2021 New module swad_assignment_database for database queries related to assignments. (310858 lines)
Version 20.74: May 11, 2021 New module swad_announcement_database for database queries related to announcements. (310629 lines)
Version 20.73: May 10, 2021 New module swad_agenda_database for database queries related to agenda. (310474 lines)
Version 20.72: May 10, 2021 New module swad_account_database for database queries related to user's account. (310328 lines)
Version 20.71: May 10, 2021 New module swad_media_database for database queries related to media. (310080 lines)

View File

@ -32,6 +32,7 @@
#include "swad_action.h"
#include "swad_agenda_database.h"
#include "swad_assignment_database.h"
#include "swad_box.h"
#include "swad_database.h"
#include "swad_error.h"
@ -3182,7 +3183,7 @@ static void Fig_GetAndShowAssignmentsStats (void)
/***** Get the number of assignments from this location *****/
if ((NumAssignments = Asg_GetNumAssignments (Gbl.Scope.Current,&NumNotif)))
if ((NumCoursesWithAssignments = Asg_GetNumCoursesWithAssignments (Gbl.Scope.Current)) != 0)
if ((NumCoursesWithAssignments = Asg_DB_GetNumCoursesWithAssignments (Gbl.Scope.Current)) != 0)
NumAssignmentsPerCourse = (double) NumAssignments /
(double) NumCoursesWithAssignments;

View File

@ -32,6 +32,7 @@
#include <string.h> // For string functions
#include "swad_action.h"
#include "swad_assignment_database.h"
#include "swad_attendance.h"
#include "swad_box.h"
#include "swad_database.h"
@ -4143,7 +4144,7 @@ static void Grp_RemoveGroupTypeCompletely (void)
Brw_RemoveZonesOfGroupsOfType (Gbl.Crs.Grps.GrpTyp.GrpTypCod);
/***** Remove the associations of assignments to groups of this type *****/
Asg_RemoveGroupsOfType (Gbl.Crs.Grps.GrpTyp.GrpTypCod);
Asg_DB_RemoveGroupsOfType (Gbl.Crs.Grps.GrpTyp.GrpTypCod);
/***** Remove the associations of attendance events to groups of this type *****/
Att_RemoveGroupsOfType (Gbl.Crs.Grps.GrpTyp.GrpTypCod);
@ -4212,7 +4213,7 @@ static void Grp_RemoveGroupCompletely (void)
Brw_RemoveGrpZones (Gbl.Hierarchy.Crs.CrsCod,GrpDat.GrpCod);
/***** Remove this group from all assignments *****/
Asg_RemoveGroup (GrpDat.GrpCod);
Asg_DB_RemoveGroup (GrpDat.GrpCod);
/***** Remove this group from all attendance events *****/
Att_RemoveGroup (GrpDat.GrpCod);

View File

@ -29,6 +29,7 @@
#include <mysql/mysql.h> // To access MySQL databases
#include "swad_action.h"
#include "swad_assignment_database.h"
#include "swad_box.h"
#include "swad_database.h"
#include "swad_department.h"
@ -1439,7 +1440,7 @@ void Ind_ComputeAndStoreIndicatorsCrs (long CrsCod,int NumIndicatorsFromDB,
IndicatorsCrs->NumIndicators++;
/***** Indicator #2: information about assignments *****/
IndicatorsCrs->NumAssignments = Asg_GetNumAssignmentsInCrs (CrsCod);
IndicatorsCrs->NumAssignments = Asg_DB_GetNumAssignmentsInCrs (CrsCod);
IndicatorsCrs->NumFilesAssignments = Ind_GetNumFilesInAssigZonesOfCrsFromDB (CrsCod);
IndicatorsCrs->NumFilesWorks = Ind_GetNumFilesInWorksZonesOfCrsFromDB (CrsCod);
IndicatorsCrs->ThereAreAssignments = (IndicatorsCrs->NumAssignments != 0) ||