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

Allow one sponsoring to target multiple teams #264

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from

Conversation

sibbl
Copy link
Contributor

@sibbl sibbl commented May 16, 2022

Work in progress

@@ -89,41 +92,49 @@ class SponsoringController(private var sponsoringService: SponsoringService,
@PreAuthorize("isAuthenticated()")
@PostMapping("/event/{eventId}/team/{teamId}/sponsoring/")
@ResponseStatus(CREATED)
fun createSponsoring(@PathVariable teamId: Long,
fun createSponsoring(@PathVariable eventId: Long,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For backwords compatibility, I'd personally like to keep this endpoint. It will accept a sponsoring be created for a single team.

We do have unit tests for it, so just adding a new endpoint in the first place should be the solution.

@@ -201,7 +201,12 @@ class Team : BasicEntity, Blockable {
}

private fun Sponsoring.toEmailListing(): String {
return "<b>Name</b> ${this.sponsor?.firstname} ${this.sponsor?.lastname} <b>Status</b> ${this.status} <b>Betrag pro km</b> ${this.amountPerKm.display()} <b>Limit</b> ${this.limit.display()} <b>Gereiste KM</b> ${this.team?.getCurrentDistance()} <b>Spendenversprechen</b> ${this.billableAmount().display()}"
var result = "<b>Name</b> ${this.sponsor?.firstname} ${this.sponsor?.lastname} <b>Status</b> ${this.status} <b>Betrag pro km</b> ${this.amountPerKm.display()} <b>Limit</b> ${this.limit.display()} <b>Spendenversprechen</b> ${this.billableAmount().display()}"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to check whether the visualization is correct this way.

We should also add a ticket for HTML encoding the content. Team names can include any HTML which is displayed here...

@@ -118,7 +118,9 @@ class SponsoringInvoice : Invoice {
}

private fun Sponsoring.toEmailListing(): String {
return "<b>Team-ID</b> ${this.team?.id} <b>Teamname</b> ${this.team?.name} <b>Status</b> ${this.status} <b>Betrag pro km</b> ${this.amountPerKm.display()} <b>Limit</b> ${this.limit.display()} <b>Gereiste KM</b> ${this.team?.getCurrentDistance()} <b>Spendenversprechen</b> ${this.billableAmount().display()}"
// TODO: implement with teams
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm honestly not sure how this should be correctly implemented.

We need to check who this is sent to? The sponsor? Each team?

Based on this we either list all teams here (if sent to sponsor) or add a team to the function parameters and only show this team's name+id+distance+km+billable amount. And not all other teams they're not interested in.

where s.id is not null or c.id is not null
left join i.sponsorings s
where c.id is not null
and exists (SELECT 1 FROM Sponsoring sp JOIN sp.teams t WHERE sp.id = s.id AND t.id = :teamId)
Copy link
Contributor Author

@sibbl sibbl May 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SQL query is kind of untested. It might also be better to use and s.id IN (SELECT sp.id FROM Sponsoring sp JOIN sp.teams t WHERE sp.id = s.id AND t.id = :teamId) but my gut told me that exist might be faster.

@ManyToOne
var team: Team? = null
@ManyToMany
var teams: MutableSet<Team> = HashSet()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose a set for now. We might also want to use a list instead. I want to make sure that each team can only be once in there, so a Set felt better as a starting point.


@ManyToOne(cascade = [PERSIST])
private var unregisteredSponsor: UnregisteredSponsor? = null

@ManyToOne
private var registeredSponsor: Sponsor? = null

@ManyToOne
var event: Event? = null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new because the event was initially read from the single team's event field. However, we theoretically might have 0 teams and thus still need to store the event relation somewhere.

@Suppress("UNUSED") //Used by Spring @PreAuthorize
fun checkWithdrawPermissions(username: String): Boolean {
return when {
this.unregisteredSponsor != null -> this.team!!.isMember(username)
this.unregisteredSponsor != null -> this.unregisteredSponsor!!.team?.isMember(username) == true
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit unsure whether this is correct. Can the one who created the sponsoring (so unregistedSponsor.team do this or any of the teams in the teams collection? Ideally it's the same team anyway.

We need to check this.

@@ -141,8 +153,9 @@ class Sponsoring : BasicEntity, Billable {
}

override fun billableAmount(): Money {

val distance: Double = team?.getCurrentDistance() ?: run {
val distance: Double = if (teams.isNotEmpty())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to implement the billing calculation across multiple teams here.

fun rejectSponsoring(sponsoring: Sponsoring): Sponsoring

@PreAuthorize("#sponsoring.checkWithdrawPermissions(authentication.name)")
fun withdrawSponsoring(sponsoring: Sponsoring): Sponsoring

@PreAuthorize("#team.isMember(authentication.name)")
fun createSponsoringWithOfflineSponsor(team: Team, amountPerKm: Money, limit: Money, unregisteredSponsor: UnregisteredSponsor): Sponsoring
@PreAuthorize("#unregisteredSponsor.team.isMember(authentication.name)")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to check how this behaves in the real world. Perhaps we might need to check isTeamMember instead.

@@ -154,7 +154,8 @@ class SponsoringServiceImpl(private val sponsoringRepository: SponsoringReposito
}

fun calculateAmount(sponsoring: Sponsoring): Money {
val kilometers = teamService.getDistanceForTeam(sponsoring.team!!.id!!)
// TODO: fix calculation
val kilometers = sponsoring.teams.sumByDouble { it.getCurrentDistance() }
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if we need to calculate this on a per team base.

var teamId: Long? = null

var team: String? = null
var teams: Map<Long, String>? = null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be adapted in the frontend.

var teamId: Long? = null

var team: String? = null
var teams: Map<Long, String>? = null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be adapted in the frontend.

@@ -37,19 +35,19 @@ class SponsoringView() {

var billableAmount: Double? = null

var teamDistance: Double? = null
var teamsTotalDistance: Double? = null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure whether the total team distance is enough in here. If we need it on a per team base, we might need to extend the teams map to not only include the name as the value but also each team's individual distance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant