Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modernize attendance tool backend #109

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ jobs:
runs-on: ubuntu-20.04
steps:
- name: Git Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: JDK 11
uses: actions/setup-java@v1
uses: actions/setup-java@v3
with:
java-version: 11
distribution: temurin
architecture: x64
cache: maven
- name: Build with Maven
env:
MAVEN_OPTS: -Djava.awt.headless=true -Dorg.slf4j.simpleLogger.defaultLogLevel=info -Dmaven.wagon.http.retryHandler.count=2 -Dmaven.wagon.http.pool=true
Expand Down
6 changes: 0 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
# Attendance
A simple [Sakai](https://github.com/sakaiproject/sakai) tool for tracking attendance that integrates with the Gradebook.

## Performance Improvements - MUST READ
With the release of 20170215, statistics are now stored in a table. As such, a job was created to calculate these stats.
This job should be run once after the deployment of 20170215; afterwards it may be run as needed or at regular interval
as determined by the administrators. The job **MUST BE** run at least once to calculate & save the statistics to begin with, afterwards the job is only needed to be run to sync up the stats to the current roster (in
the case of users attending an item and then later leaving the site). This job is titled "Attendance Stat Calc - SEE DOCS".

## Resources
Pages: http://sakaicontrib.github.io/attendance/

Expand Down
29 changes: 15 additions & 14 deletions api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>attendance</artifactId>
<groupId>org.sakaiproject.attendance</groupId>
<version>23-SNAPSHOT</version>
</parent>
<artifactId>attendance</artifactId>
<groupId>org.sakaiproject.attendance</groupId>
<version>24-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<name>attendance - API</name>
<artifactId>attendance-api</artifactId>
Expand All @@ -36,24 +37,24 @@
<!-- project dependencies -->

<!-- third party dependencies -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>

<!-- Sakai dependencies -->
<dependency>
<groupId>org.sakaiproject.kernel</groupId>
<artifactId>sakai-kernel-api</artifactId>
</dependency>
<dependency>
<groupId>org.sakaiproject.kernel</groupId>
<artifactId>sakai-kernel-api</artifactId>
</dependency>
</dependencies>

<build />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

package org.sakaiproject.attendance.api;

import org.sakaiproject.attendance.model.AttendanceGrade;
import org.sakaiproject.attendance.model.AttendanceSite;
import org.sakaiproject.attendance.api.model.AttendanceGrade;
import org.sakaiproject.attendance.api.model.AttendanceSite;

import java.util.List;
import java.util.Map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
* limitations under the License.
*/

package org.sakaiproject.attendance.export;
package org.sakaiproject.attendance.api.export;

import org.sakaiproject.attendance.model.AttendanceEvent;
import org.sakaiproject.attendance.api.model.AttendanceEvent;
import org.sakaiproject.user.api.User;

import java.io.OutputStream;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,16 @@
* limitations under the License.
*/

package org.sakaiproject.attendance.logic;
package org.sakaiproject.attendance.api.logic;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.sakaiproject.attendance.model.*;
import org.sakaiproject.attendance.api.model.*;
import org.sakaiproject.attendance.api.model.stats.AttendanceItemStats;
import org.sakaiproject.attendance.api.model.stats.AttendanceStats;
import org.sakaiproject.attendance.api.model.stats.AttendanceUserStats;
import org.sakaiproject.entity.api.EntityProducer;

/**
Expand All @@ -37,16 +40,16 @@ public interface AttendanceLogic extends EntityProducer {
*
* @param siteID, sakai Site ID
* @return the Attendance Site
*/
*/
AttendanceSite getAttendanceSite(String siteID);

/**
* Updates an AttendanceSite
*
* @param aS, the AttendanceSite to update (must not be null)
* @return success of the operation
*/
boolean updateAttendanceSite(AttendanceSite aS) throws IllegalArgumentException;
*/
AttendanceSite updateAttendanceSite(AttendanceSite aS) throws IllegalArgumentException;

/**
* Get's the current AttendanceSite
Expand Down Expand Up @@ -82,32 +85,31 @@ public interface AttendanceLogic extends EntityProducer {
*
* @param e, the AttendanceEvent to add
* @return the Long ID of the AttendanceEvent added
*/
Serializable addAttendanceEventNow(AttendanceEvent e);
*/
AttendanceEvent addAttendanceEventNow(AttendanceEvent e);

/**
* Updates an AttendanceEvent
*
* @param aE, the event to update (must not be null)
* @return success of the operation
*/
boolean updateAttendanceEvent(AttendanceEvent aE) throws IllegalArgumentException;
*/
AttendanceEvent updateAttendanceEvent(AttendanceEvent aE) throws IllegalArgumentException;

/**
* Deletes an AttendanceEvent
*
* @param aE, the event to delete (must not be null) // though this can probably be changed
* @return success of the operation
*/
boolean deleteAttendanceEvent(AttendanceEvent aE) throws IllegalArgumentException;
*/
void deleteAttendanceEvent(AttendanceEvent aE) throws IllegalArgumentException;

/**
* Get's an AttendanceRecord by ID
*
* @param id, the id of the attendanceRecord
* @return the attendanceRecord
*/
AttendanceRecord getAttendanceRecord(Long id);
*/
Optional<AttendanceRecord> getAttendanceRecord(Long id);

/**
* get AttendanceRecords For a User in the current site
Expand Down Expand Up @@ -154,16 +156,16 @@ public interface AttendanceLogic extends EntityProducer {
*
* @param id, the id of the AttendanceStatus
* @return the AttendanceStatus
*/
AttendanceStatus getAttendanceStatusById(Long id);
*/
Optional<AttendanceStatus> getAttendanceStatusById(Long id);

/**
* Update an AttendanceRecord
*
* @param aR, the AttendanceRecord to update (must not be null)
* @return the success of the operation
*/
boolean updateAttendanceRecord(AttendanceRecord aR, Status oldStatus) throws IllegalArgumentException;
*/
AttendanceRecord updateAttendanceRecord(AttendanceRecord aR, Status oldStatus) throws IllegalArgumentException;

/**
* Update all AttendanceRecords for an AttendanceEvent
Expand All @@ -180,7 +182,7 @@ public interface AttendanceLogic extends EntityProducer {
* @param aE, the AttendanceEvent
* @param s, the Status to use (if null, use the Site's default status)
* @param groupId, only update the AttendanceRecords for members of the groupID (if null or empty calls
* {@link org.sakaiproject.attendance.logic.AttendanceLogic#updateAttendanceRecordsForEvent(AttendanceEvent, Status)})
* {@link AttendanceLogic#updateAttendanceRecordsForEvent(AttendanceEvent, Status)})
*/
void updateAttendanceRecordsForEvent(AttendanceEvent aE, Status s, String groupId);

Expand Down Expand Up @@ -240,8 +242,8 @@ public interface AttendanceLogic extends EntityProducer {
*
* @param id, the ID (must not be null)
* @return the AttendanceGrade
*/
AttendanceGrade getAttendanceGrade(Long id) throws IllegalArgumentException;
*/
Optional<AttendanceGrade> getAttendanceGrade(Long id) throws IllegalArgumentException;

/**
* Get's the AttendanceGrade for user in current site
Expand Down Expand Up @@ -271,8 +273,8 @@ public interface AttendanceLogic extends EntityProducer {
*
* @param aG, the AG to update (must not be null)
* @return the success of the operation
*/
boolean updateAttendanceGrade(AttendanceGrade aG) throws IllegalArgumentException;
*/
AttendanceGrade updateAttendanceGrade(AttendanceGrade aG) throws IllegalArgumentException;

/**
* Returns the stats for a specified Status from an AttendanceStats object
Expand All @@ -288,15 +290,14 @@ public interface AttendanceLogic extends EntityProducer {
* @param gradingRule, The GradingRule to be added.
* @return the success of the operation
*/
boolean addGradingRule(GradingRule gradingRule);
GradingRule addGradingRule(GradingRule gradingRule);

/**
* Deletes a grading rule.
*
* @param gradingRule, The GradingRule to be deleted.
* @return the success of the operation
*/
boolean deleteGradingRule(GradingRule gradingRule);
void deleteGradingRule(GradingRule gradingRule);

/**
* Get a list of Grading Rules that have been created for a given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

package org.sakaiproject.attendance.logic;
package org.sakaiproject.attendance.api.logic;

import org.sakaiproject.user.api.User;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright (c) 2017, University of Dayton
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://opensource.org/licenses/ecl2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sakaiproject.attendance.api.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Type;
import org.hibernate.proxy.HibernateProxy;
import org.sakaiproject.springframework.data.PersistableEntity;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import java.io.Serializable;
import java.time.Instant;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
* Represents an AttendanceEvent, such as a class meeting or seminar
*
* @author Leonardo Canessa [lcanessa1 (at) udayton (dot) edu])
* @author David Bauer [dbauer1 (at) udayton (dot) edu]
* @author Steve Swinsburg (steve.swinsburg@gmail.com)
*/
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "ATTENDANCE_EVENT_T")
@Getter
@Setter
@RequiredArgsConstructor
@ToString
@AllArgsConstructor
public class AttendanceEvent implements Serializable, PersistableEntity<Long> {
private static final long serialVersionUID = 1L;

@Id
@Column(name = "A_EVENT_ID", length = 19)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "attendance_event_id_sequence")
@SequenceGenerator(name = "attendance_event_id_sequence", sequenceName = "ATTENDANCE_EVENT_S")
private Long id;

@Column(name = "NAME")
private String name;

@Type(type = "org.hibernate.type.InstantType")
@Column(name = "START_DATE_TIME")
private Instant startDateTime;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "A_SITE_ID")
@ToString.Exclude
private AttendanceSite attendanceSite;

@OneToMany(mappedBy = "attendanceEvent", cascade = CascadeType.ALL, orphanRemoval = true)
@ToString.Exclude
private Set<AttendanceRecord> records = new HashSet<>(0);

// Copy constructor
public AttendanceEvent(AttendanceEvent attendanceEvent) {
this.name = attendanceEvent.name;
this.startDateTime = attendanceEvent.startDateTime;
this.attendanceSite = attendanceEvent.attendanceSite;
}

@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
Class<?> oEffectiveClass = o instanceof HibernateProxy ? ((HibernateProxy) o).getHibernateLazyInitializer().getPersistentClass() : o.getClass();
Class<?> thisEffectiveClass = this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass() : this.getClass();
if (thisEffectiveClass != oEffectiveClass) return false;
AttendanceEvent that = (AttendanceEvent) o;
return getId() != null && Objects.equals(getId(), that.getId());
}

@Override
public final int hashCode() {
return this instanceof HibernateProxy ? ((HibernateProxy) this).getHibernateLazyInitializer().getPersistentClass().hashCode() : getClass().hashCode();
}
}
Loading
Loading