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

Support floating point hours for volunteering. #2813

Open
wants to merge 2 commits into
base: develop
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
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,16 @@ public class VolunteeringEvent {

@Column(name = "hours")
@Schema(description = "number of hours spent volunteering")
@TypeDef(type = DataType.INTEGER)
private int hours;
@TypeDef(type = DataType.DOUBLE)
private double hours;

@Nullable
@Column(name = "notes")
@TypeDef(type = DataType.STRING)
@Schema(description = "notes about the volunteering event")
private String notes;

public VolunteeringEvent(UUID relationshipId, LocalDate eventDate, int hours, String notes) {
public VolunteeringEvent(UUID relationshipId, LocalDate eventDate, double hours, String notes) {
this(null, relationshipId, eventDate, hours, notes);
}

Expand All @@ -79,4 +79,4 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(id, relationshipId, eventDate, hours, notes);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ public class VolunteeringEventDTO {

@NotNull
@Schema(description = "number of hours spent volunteering")
private Integer hours;
private Double hours;

@Nullable
@Schema(description = "notes about the volunteering event")
private String notes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE volunteering_event
ALTER COLUMN hours TYPE float;
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ default VolunteeringRelationship createVolunteeringRelationship(UUID memberId, U
return getVolunteeringRelationshipRepository().save(new VolunteeringRelationship(memberId, organizationId, startDate, endDate, active));
}

default VolunteeringEvent createVolunteeringEvent(UUID relationshipId, LocalDate now, int i, String notes) {
default VolunteeringEvent createVolunteeringEvent(UUID relationshipId, LocalDate now, double i, String notes) {
return getVolunteeringEventRepository().save(new VolunteeringEvent(relationshipId, now, i, notes));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

@Property(name = VolunteeringClients.Event.ENABLED, value = "true")
class VolunteeringEventControllerTest extends TestContainersSuite implements MemberProfileFixture, RoleFixture, VolunteeringFixture {
static final double fiveHours = 5.0;
static final double tenHours = 10.0;

@Inject
VolunteeringClients.Event eventClient;
Expand Down Expand Up @@ -63,7 +65,7 @@ void memberCanCreateEventForTheirRelationships() {
LocalDate now = LocalDate.now();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);

var event = new VolunteeringEventDTO(relationship.getId(), now, 10, "Notes");
var event = new VolunteeringEventDTO(relationship.getId(), now, tenHours, "Notes");
var createdEvent = eventClient.create(timAuth, event);

assertEquals(HttpStatus.CREATED, createdEvent.getStatus());
Expand All @@ -83,7 +85,7 @@ void memberCannotCreateEventForSomeoneElseRelationships() {
LocalDate now = LocalDate.now();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);

var event = new VolunteeringEventDTO(relationship.getId(), now, 10, "Notes");
var event = new VolunteeringEventDTO(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), MEMBER_ROLE);
Expand All @@ -104,7 +106,7 @@ void memberWithPermissionCanCreateEventForSomeoneElseRelationships() {
MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), ADMIN_ROLE);

var event = new VolunteeringEventDTO(relationship.getId(), now, 10, "Notes");
var event = new VolunteeringEventDTO(relationship.getId(), now, tenHours, "Notes");
var createdEvent = eventClient.create(bobAuth, event);

assertEquals(HttpStatus.CREATED, createdEvent.getStatus());
Expand All @@ -124,9 +126,9 @@ void memberCanUpdateTheirOwnEvents() {

VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

var updated = eventClient.update(timAuth, event.getId(), new VolunteeringEventDTO(relationship.getId(), now, 5, "New notes"));
var updated = eventClient.update(timAuth, event.getId(), new VolunteeringEventDTO(relationship.getId(), now, fiveHours, "New notes"));
assertEquals(event.getId(), updated.getId());
assertEquals("New notes", updated.getNotes());
}
Expand All @@ -138,12 +140,12 @@ void memberCannotUpdateOthersEvents() {

VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), MEMBER_ROLE);

var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(relationship.getId(), now, 5, "New notes")));
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(relationship.getId(), now, fiveHours, "New notes")));
assertEquals(HttpStatus.BAD_REQUEST, e.getStatus());
assertEquals("Member %s does not have permission to update Volunteering event for relationship %s".formatted(bob.getId(), relationship.getId()), e.getMessage());
}
Expand All @@ -157,12 +159,12 @@ void memberCannotUpdateTheirEventToSomeoneElse() {

VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
VolunteeringRelationship bobRelationship = createVolunteeringRelationship(bob.getId(), organization.getId(), now);

var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(timAuth, event.getId(), new VolunteeringEventDTO(bobRelationship.getId(), now, 5, "New notes")));
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(timAuth, event.getId(), new VolunteeringEventDTO(bobRelationship.getId(), now, fiveHours, "New notes")));
assertEquals(HttpStatus.BAD_REQUEST, e.getStatus());
assertEquals("Member %s does not have permission to update Volunteering event for relationship %s".formatted(tim.getId(), bobRelationship.getId()), e.getMessage());
}
Expand All @@ -175,13 +177,13 @@ void memberCannotUpdateSomeoneElseEventToTheirs() {

VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), MEMBER_ROLE);
VolunteeringRelationship bobRelationship = createVolunteeringRelationship(bob.getId(), organization.getId(), now);

var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(bobRelationship.getId(), now, 5, "New notes")));
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(bobRelationship.getId(), now, fiveHours, "New notes")));
assertEquals(HttpStatus.BAD_REQUEST, e.getStatus());
assertEquals("Member %s does not have permission to update Volunteering event for relationship %s".formatted(bob.getId(), relationship.getId()), e.getMessage());
}
Expand All @@ -192,13 +194,13 @@ void memberCannotHackUpdateOthersEventsWithTheirOwnRelationship() {
MemberProfile tim = createADefaultMemberProfile();
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), MEMBER_ROLE);
VolunteeringRelationship bobsRelationship = createVolunteeringRelationship(bob.getId(), organization.getId(), now);

var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(bobsRelationship.getId(), now, 5, "New notes")));
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(bobsRelationship.getId(), now, fiveHours, "New notes")));
assertEquals(HttpStatus.BAD_REQUEST, e.getStatus());
assertEquals("Member %s does not have permission to update Volunteering event for relationship %s".formatted(bob.getId(), relationship.getId()), e.getMessage());
}
Expand All @@ -209,12 +211,12 @@ void memberCanUpdateOthersEventsWithProperPermission() {
MemberProfile tim = createADefaultMemberProfile();
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), ADMIN_ROLE);

var updated = eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(relationship.getId(), now, 5, "New notes"));
var updated = eventClient.update(bobAuth, event.getId(), new VolunteeringEventDTO(relationship.getId(), now, fiveHours, "New notes"));
assertEquals(event.getId(), updated.getId());
assertEquals("New notes", updated.getNotes());
}
Expand All @@ -226,7 +228,7 @@ void memberCanDeleteTheirOwnEvents() {
String timAuth = auth(tim.getWorkEmail(), MEMBER_ROLE);
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

var deletedEvent = eventClient.delete(timAuth, event.getId());
assertEquals(HttpStatus.OK, deletedEvent.getStatus());
Expand All @@ -238,7 +240,7 @@ void memberCannotDeleteOthersEvents() {
MemberProfile tim = createADefaultMemberProfile();
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), MEMBER_ROLE);
Expand All @@ -254,7 +256,7 @@ void memberWithPermissionCanDeleteOthersEvents() {
MemberProfile tim = createADefaultMemberProfile();
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

MemberProfile bob = memberWithoutBoss("bob");
String bobAuth = auth(bob.getWorkEmail(), ADMIN_ROLE);
Expand Down Expand Up @@ -304,13 +306,13 @@ void eventListCanBeFiltered() {
var bobClosed = createVolunteeringRelationship(bob.getId(), closedOrg.getId(), now.minusDays(100), now.minusDays(50), false);
var clairClosed = createVolunteeringRelationship(claire.getId(), closedOrg.getId(), now.minusDays(1), now);

var aliceLiftEvent1 = createVolunteeringEvent(aliceLiftForLife.getId(), now.minusDays(2), 10, "aliceLiftEvent1"); // 2 days ago
var aliceLiftEvent1 = createVolunteeringEvent(aliceLiftForLife.getId(), now.minusDays(2), tenHours, "aliceLiftEvent1"); // 2 days ago
var aliceLiftEvent2 = createVolunteeringEvent(aliceLiftForLife.getId(), now, 8, "aliceLiftEvent2"); // today
var bobLiftEvent1 = createVolunteeringEvent(bobLiftForLife.getId(), now, 6, "bobLiftEvent1"); // today
var clairLiftEvent1 = createVolunteeringEvent(claireLiftForLife.getId(), now.minusDays(3), 4, "clairLiftEvent1"); // 3 days ago
var aliceFoodEvent1 = createVolunteeringEvent(aliceFood.getId(), now.minusDays(20), 2, "aliceFoodEvent1"); // 20 days ago
var clairFoodEvent1 = createVolunteeringEvent(claireFood.getId(), now, 1, "clairFoodEvent1"); // today
var bobClosedEvent1 = createVolunteeringEvent(bobClosed.getId(), now.minusDays(76), 10, "bobClosedEvent1"); // 76 days ago
var bobClosedEvent1 = createVolunteeringEvent(bobClosed.getId(), now.minusDays(76), tenHours, "bobClosedEvent1"); // 76 days ago
var clairClosedEvent1 = createVolunteeringEvent(clairClosed.getId(), now.minusDays(1), 0, "clairClosedEvent1"); // yesterday

// List all events, sorted by event date and then by organization name
Expand Down Expand Up @@ -353,10 +355,10 @@ void relationshipMustExist() {
String timAuth = auth(tim.getWorkEmail(), MEMBER_ROLE);
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");
UUID randomId = UUID.randomUUID();

VolunteeringEventDTO newEvent = new VolunteeringEventDTO(randomId, now, 10, "Notes");
VolunteeringEventDTO newEvent = new VolunteeringEventDTO(randomId, now, tenHours, "Notes");

// Creating an event with a non-existent relationship should fail
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.create(timAuth, newEvent));
Expand All @@ -376,9 +378,9 @@ void eventDateMustBeSet() {
String timAuth = auth(tim.getWorkEmail(), MEMBER_ROLE);
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

VolunteeringEventDTO newEvent = new VolunteeringEventDTO(relationship.getId(), null, 10, "Notes");
VolunteeringEventDTO newEvent = new VolunteeringEventDTO(relationship.getId(), null, tenHours, "Notes");

// Creating an event with a null date should fail
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.create(timAuth, newEvent));
Expand All @@ -400,9 +402,9 @@ void hoursMustBeNonNegative() {
String timAuth = auth(tim.getWorkEmail(), MEMBER_ROLE);
VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");

VolunteeringEventDTO newEvent = new VolunteeringEventDTO(relationship.getId(), now, -1, "Notes");
VolunteeringEventDTO newEvent = new VolunteeringEventDTO(relationship.getId(), now, -1.0, "Notes");

// Creating an event with negative hours should fail
var e = assertThrows(HttpClientResponseException.class, () -> eventClient.create(timAuth, newEvent));
Expand All @@ -422,7 +424,7 @@ void hoursAreRequired() {

VolunteeringOrganization organization = createDefaultVolunteeringOrganization();
VolunteeringRelationship relationship = createVolunteeringRelationship(tim.getId(), organization.getId(), now);
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, 10, "Notes");
VolunteeringEvent event = createVolunteeringEvent(relationship.getId(), now, tenHours, "Notes");
String postBody = """
{
"relationshipId": "%s",
Expand Down
Loading