Skip to content

Commit

Permalink
Merge d4c9600 into c08f051
Browse files Browse the repository at this point in the history
  • Loading branch information
sery0ga committed Mar 30, 2015
2 parents c08f051 + d4c9600 commit 1a1c265
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 46 deletions.
5 changes: 3 additions & 2 deletions app/controllers/EventTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,15 @@ trait EventTypes extends Controller with Security with Services {
"brandId" -> nonEmptyText.transform(_.toLong,
(l: Long) l.toString).verifying((brandId: Long) brandService.find(brandId).isDefined),
"name" -> nonEmptyText(maxLength = 254),
"title" -> optional(text(maxLength = 254)))(EventType.apply)(EventType.unapply))
"title" -> optional(text(maxLength = 254)),
"maxhours" -> number(min = 1))(EventType.apply)(EventType.unapply))

implicit val eventTypeWrites = new Writes[EventType] {
def writes(data: EventType): JsValue = {
Json.obj(
"name" -> data.name,
"title" -> data.defaultTitle,
"maxhours" -> data.maxHours,
"id" -> data.id.get)
}
}
Expand Down Expand Up @@ -95,7 +97,6 @@ trait EventTypes extends Controller with Security with Services {
eventTypeService.find(id) map { x
eventTypeForm.bindFromRequest.fold(
hasErrors {
println(hasErrors.errors.toString)
BadRequest(Json.toJson(Json.obj(
"message" -> Messages("event.eventType.notFound"))))
},
Expand Down
25 changes: 16 additions & 9 deletions app/controllers/Events.scala
Original file line number Diff line number Diff line change
Expand Up @@ -305,18 +305,25 @@ object Events extends Controller
def details(id: Long) = SecuredRestrictedAction(Viewer) { implicit request
implicit handler implicit user

eventService.find(id) map { event
//@TODO only funders must be retrieved
val funders = Organisation.findAll
eventService.find(id) map { x
val acc = user.account
val typeName = eventTypeService.find(event.eventTypeId) map {
_.name
} getOrElse ""
val canFacilitate = acc.editor || event.canFacilitate(acc.personId)
val fees = feeService.findByBrand(event.brandCode).
//@TODO only funders must be retrieved
val funders = if (acc.editor) Organisation.findAll else List()
val eventType = eventTypeService.find(x.eventTypeId).get
val canFacilitate = acc.editor || x.canFacilitate(acc.personId)
val fees = feeService.findByBrand(x.brandCode)
val printableFees = fees.
map(x (Countries.name(x.country), x.fee.toString)).
sortBy(_._1)
Ok(views.html.event.details(user, canFacilitate, funders, event, typeName, fees))
val event = fees.find(_.country == x.location.countryCode) map { y
Event.withFee(x, y.fee, eventType.maxHours)
} getOrElse x
Ok(views.html.event.details(user,
canFacilitate,
funders,
event,
eventType.name,
printableFees))
} getOrElse NotFound
}

Expand Down
8 changes: 5 additions & 3 deletions app/models/Event.scala
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,12 @@ object Event {
* Returns new event with a fee calculated the given one and a number of hours
* @param event Source event
* @param fee Country Fee for 16-hours event
* @param maxHours Maximum number of chargeable hours
*/
def withFee(event: Event, fee: Money): Event = {
val hours = event.schedule.totalHours.toLong
val eventFee = fee.multipliedBy(hours).dividedBy(16L, java.math.RoundingMode.UNNECESSARY)
def withFee(event: Event, fee: Money, maxHours: Int): Event = {
val hours = scala.math.min(maxHours, event.schedule.totalHours)
val slotNumber = hours / 4 + (hours % 4).min(1)
val eventFee = fee.multipliedBy(slotNumber).dividedBy(4L, java.math.RoundingMode.UNNECESSARY)
event.copy(fee = Some(eventFee))
}

Expand Down
5 changes: 3 additions & 2 deletions app/models/brand/EventType.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import play.api.db.slick.DB
case class EventType(id: Option[Long],
brandId: Long,
name: String,
defaultTitle: Option[String]) extends ActivityRecorder {
defaultTitle: Option[String],
maxHours: Int) extends ActivityRecorder {

/**
* Returns identifier of the object
Expand Down Expand Up @@ -74,7 +75,7 @@ object EventType {
}

def delete(id: Long): Unit = DB.withSession { implicit session: Session
EventTypes.filter(_.id === id).mutate(_.delete)
EventTypes.filter(_.id === id).mutate(_.delete())
}

}
6 changes: 4 additions & 2 deletions app/models/database/brand/EventTypes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ private[models] object EventTypes extends Table[EventType]("EVENT_TYPE") {
def brandId = column[Long]("BRAND_ID")
def name = column[String]("NAME")
def defaultTitle = column[Option[String]]("DEFAULT_TITLE")
def maxHours = column[Int]("MAX_HOURS")

def brand = foreignKey("EVENT_BRAND_FK", brandId, Brands)(_.id)

def * = id.? ~ brandId ~ name ~ defaultTitle <> (EventType.apply _, EventType.unapply _)
def * = id.? ~ brandId ~ name ~ defaultTitle ~
maxHours <> (EventType.apply _, EventType.unapply _)

def forInsert = * returning id
def forUpdate = name ~ defaultTitle
def forUpdate = name ~ defaultTitle ~ maxHours
}
10 changes: 1 addition & 9 deletions app/models/service/EventService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,7 @@ class EventService extends Notifiers with Services {
*/
def find(id: Long): Option[Event] = DB.withSession {
implicit session: Session
val query = for {
(event, fee) Events leftJoin
BrandFees on ((e, f) e.brandCode === f.brand && e.countryCode === f.country) if event.id === id
} yield (event, fee.feeCurrency.?, fee.feeAmount.?)
query.list.headOption map { v
val e = v._2 map { currency Event.withFee(v._1, currency -> v._3.get)
} getOrElse v._1
Some(e)
} getOrElse None
Query(Events).filter(_.id === id).firstOption
}

/**
Expand Down
2 changes: 1 addition & 1 deletion app/models/service/brand/EventTypeService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class EventTypeService {
*/
def update(value: EventType): EventType = DB.withSession {
implicit session: Session
val tuple = (value.name, value.defaultTitle)
val tuple = (value.name, value.defaultTitle, value.maxHours)
Query(EventTypes).filter(_.id === value.id).map(_.forUpdate).update(tuple)
value
}
Expand Down
7 changes: 5 additions & 2 deletions app/views/brand/tabs/eventTypes.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
<tr>
<th>Name</th>
<th>Default Title</th>
<th>Max hours</th>
<th></th>
</tr>
</thead>
Expand All @@ -23,6 +24,7 @@
<tr data-id="@eventType.id.get" data-brandid="@eventType.brandId">
<td data-name="name">@eventType.name</td>
<td data-name="title">@eventType.defaultTitle</td>
<td data-name="maxhours">@eventType.maxHours</td>
<th style="font-weight: normal;">
@restrict(handler, List(as(Editor.toString))) {
<a href="@routes.EventTypes.delete(eventType.id.get)">
Expand All @@ -37,8 +39,9 @@
<form class="form-inline pull-right col-sm-8" method="POST" action="@CSRF(routes.EventTypes.create())" id="eventType">
<input type="hidden" name="brandId" value="@brand.id"/>
<div>
<input name="name" class="form-control input-sm" style="width: 28%;" placeholder="Ex: Regular 2-Day course"/>
<input name="title" class="form-control input-sm" style="width: 49%;" placeholder="Ex: Regular Management 3.0 Course"/>
<input name="name" class="form-control input-sm" style="width: 20%;" placeholder="Ex: Regular 2-Day course"/>
<input name="title" class="form-control input-sm" style="width: 40%;" placeholder="Ex: Regular Management 3.0 Course"/>
<input name="maxhours" class="form-control input-sm" style="width: 15%;" />
<button class="btn btn-success btn-sm pull-right">
<i class="glyphicon glyphicon-plus"></i>Add Event Type
</button>
Expand Down
2 changes: 1 addition & 1 deletion conf/application.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# If true, emails won't be sent, only printed into a standard output
mail.stub = false
mail.stub = true

akka.jvm-exit-on-fatal-error = off

Expand Down
5 changes: 5 additions & 0 deletions conf/evolutions/default/84.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# --- !Ups
alter table EVENT_TYPE add column MAX_HOURS int default 16;

# --- !Downs
alter table EVENT_TYPE drop column MAX_HOURS;
10 changes: 6 additions & 4 deletions test/controllers/acceptance/EventTypesSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,9 @@ class EventTypesSpec extends PlayAppSpec {

def e4 = new MockContext {
val req = prepareSecuredPostRequest(FakeUserIdentity.editor, "/").
withFormUrlEncodedBody(("id", "1"), ("brandId", "1"), ("name", "Test"))
val eventType = EventType(Some(1L), 1L, "Test", Some("test type"))
withFormUrlEncodedBody(("id", "1"), ("brandId", "1"), ("name", "Test"),
("maxhours", "16"))
val eventType = EventType(Some(1L), 1L, "Test", Some("test type"), 16)
val eventTypeService = mock[FakeEventTypeService]
(eventTypeService.find _).expects(1L).returning(Some(eventType))
val types = List(eventType.copy(id = Some(2L)))
Expand All @@ -98,8 +99,9 @@ class EventTypesSpec extends PlayAppSpec {

def e5 = new MockContext {
val req = prepareSecuredPostRequest(FakeUserIdentity.editor, "/").
withFormUrlEncodedBody(("id", "1"), ("brandId", "1"), ("name", "Test"))
val eventType = EventType(Some(1L), 1L, "Test", Some("test type"))
withFormUrlEncodedBody(("id", "1"), ("brandId", "1"),
("name", "Test"), ("maxhours", "16"))
val eventType = EventType(Some(1L), 1L, "Test", Some("test type"), 16)
val eventTypeService = mock[FakeEventTypeService]
(eventTypeService.find _).expects(1L).returning(Some(eventType))
(eventTypeService.findByBrand _).expects(1L).returning(List())
Expand Down
4 changes: 2 additions & 2 deletions test/models/integration/EventServiceSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class EventServiceSpec extends PlayAppSpec {
PersonHelper.make(Some(4L), "Four", "Tester").insert
PersonHelper.make(Some(5L), "Four", "Tester").insert
BrandHelper.one.insert
(new EventType(None, 1L, "Type 1", None)).insert
(new EventType(None, 1L, "Type 2", None)).insert
(new EventType(None, 1L, "Type 1", None, 16)).insert
(new EventType(None, 1L, "Type 2", None, 16)).insert
EventHelper.addEvents(BrandHelper.one.code)
EventHelper.addEvents("MGT30")
}
Expand Down
32 changes: 25 additions & 7 deletions test/models/unit/EventSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class EventSpec extends PlayAppSpec {
PersonHelper.make(Some(4L), "Four", "Tester").insert
PersonHelper.make(Some(5L), "Four", "Tester").insert
BrandHelper.one.insert
(new EventType(None, 1L, "Type 1", None)).insert
(new EventType(None, 1L, "Type 2", None)).insert
(new EventType(None, 1L, "Type 1", None, 16)).insert
(new EventType(None, 1L, "Type 2", None, 16)).insert
EventHelper.addEvents(BrandHelper.one.code)
EventHelper.addEvents("MGT30")
}
Expand Down Expand Up @@ -132,14 +132,32 @@ class EventSpec extends PlayAppSpec {
}
}

"Event singleton" should {
"make an event without fee" in {
val event = EventHelper.one
"Event fee " should {
"be rounded to a multiple of half a day" in {
val e1 = EventHelper.one
val fee = Money.parse("EUR 160")
val maxHours = 16
// total hours = 1
Event.withFee(event, fee).fee map { f: Money
f.getAmount.longValue must_== 10L
Event.withFee(e1, fee, maxHours).fee map { f: Money
f.getAmount.longValue must_== 40L
} getOrElse ko
val e2 = e1.copy(schedule = e1.schedule.copy(totalHours = 5))
Event.withFee(e2, fee, maxHours).fee map { f: Money
f.getAmount.longValue must_== 80L
} getOrElse ko
val e3 = e1.copy(schedule = e1.schedule.copy(totalHours = 11))
Event.withFee(e3, fee, maxHours).fee map { f: Money
f.getAmount.longValue must_== 120L
} getOrElse ko
val e4 = e1.copy(schedule = e1.schedule.copy(totalHours = 16))
Event.withFee(e4, fee, maxHours).fee map { f: Money
f.getAmount.longValue must_== 160L
} getOrElse ko
val e5 = e1.copy(schedule = e1.schedule.copy(totalHours = 21))
Event.withFee(e5, fee, maxHours).fee map { f: Money
f.getAmount.longValue must_== 160L
} getOrElse ko
}

}
}
4 changes: 2 additions & 2 deletions test/models/unit/EventTypeSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class EventTypeSpec extends Specification {

"Event type" should {
"have well-formed activity attributes" in {
val eventType = new EventType(Some(1L), 1L, "Test", None)
val eventType = new EventType(Some(1L), 1L, "Test", None, 16)
eventType.objectType must_== Activity.Type.EventType
eventType.identifier must_== 1
eventType.humanIdentifier must_== "Test"
val eventType2 = new EventType(Some(2L), 2L, "Boogy", None)
val eventType2 = new EventType(Some(2L), 2L, "Boogy", None, 16)
eventType2.objectType must_== Activity.Type.EventType
eventType2.identifier must_== 2
eventType2.humanIdentifier must_== "Boogy"
Expand Down

0 comments on commit 1a1c265

Please sign in to comment.