package controllers import org.omg.CosNaming._BindingIteratorImplBase import play.api._ import play.api.data._ import play.api.data.Forms._ import play.api.mvc._ import play.api.db.slick._ import play.api.db.slick.Config.driver.simple._ import play.api.Play.current import scala.concurrent.Future import models._ case class SaleData(endDate: java.sql.Date, name: String, shortDescription: String, longDescription: String, initialPrice: BigDecimal) case class BidData(offer: BigDecimal) object Sale extends Controller { def sales = Auth { implicit request => DB.withSession { implicit session => val currentDateTime = new java.sql.Timestamp((new java.util.Date).getTime) val sales = Views.Sales.filter(_.endDate > currentDateTime).sortBy(_.endDate.asc).run Ok(views.html.pages.sales.currentSales(sales)) } } val saleForm = Form( mapping( "endDate" -> sqlDate, "name" -> nonEmptyText(minLength = 5, maxLength = 20), "shortDescription" -> nonEmptyText(minLength = 10, maxLength = 30), "longDescription" -> nonEmptyText, "initialPrice" -> bigDecimal(precision = 8, scale = 2) )(SaleData.apply)(SaleData.unapply) ) def sell = Auth { implicit request => if (request.account.isEmpty) { Redirect(routes.Authentication.login()) .flashing("error" -> "Authentication required") } else { Ok(views.html.pages.sales.sellForm(saleForm)) } } def sellSubmit = Auth { implicit request => if (request.account.isEmpty) { Redirect(routes.Authentication.login()) .flashing("error" -> "Authentication required") } else { DB.withSession { implicit session => saleForm.bindFromRequest.fold( formWithErrors => { BadRequest(views.html.pages.sales.sellForm(formWithErrors)) }, validForm => { val items = Tables.Items returning Tables.Items.map(_.uuid) val uuid = items += Tables.Item( userUuid = request.account.get.userUuid.get, startDate = new java.sql.Timestamp(new java.util.Date().getTime), endDate = new java.sql.Timestamp(validForm.endDate.getTime), itemName = validForm.name, shortDesc = validForm.shortDescription, longDesc = validForm.longDescription, initialPrice = validForm.initialPrice ) Redirect(routes.Application.index()) .flashing("success" -> "Your item is now on sale.") } ) } } } val bidForm = Form( mapping( "offer" -> bigDecimal(precision = 8, scale = 2) )(BidData.apply)(BidData.unapply) ) def item(itemUuid: String) = Auth { implicit request => DB.withSession { implicit session => val item = Some(Tables.Items.filter(_.uuid === itemUuid).first) if (item.isEmpty) { Redirect(routes.Sale.sales()) .flashing("error" -> "Item not found") } else { val seller = Tables.Users.filter(_.uuid === item.get.userUuid).first val bids = Tables.Bids.filter(_.itemUuid === item.get.uuid).sortBy(_.bidDate.desc) val bidders = Tables.Users val bidsWithBidders = (bids join bidders on (_.userUuid === _.uuid)).run Ok(views.html.pages.sales.itemPage(item.get, seller, bidsWithBidders, bidForm)) } } } def bidSubmit(itemUuid: String) = Auth { implicit request => if (request.account.isEmpty) { Redirect(routes.Authentication.login()) .flashing("error" -> "Authentication required") } else { DB.withSession { implicit session => val item = Some(Tables.Items.filter(_.uuid === itemUuid).first) val currentTimestamp = new java.sql.Timestamp((new java.util.Date).getTime) if (item.isEmpty) { Redirect(routes.Sale.sales()) .flashing("error" -> "Item not found") } else if (item.get.endDate before currentTimestamp) { Redirect(routes.Sale.item(itemUuid)) .flashing("error" -> "This sale has already ended") } else { bidForm.bindFromRequest.fold( formsWithErrors => { Redirect(routes.Sale.item(itemUuid)) .flashing("error" -> "Invalid bid") }, validForm => { val bids = Tables.Bids.filter(_.itemUuid === itemUuid).sortBy(_.bidDate.desc).run val offersEnough = validForm.offer > item.get.initialPrice && (bids.isEmpty || validForm.offer > bids.head.offer) val userEquity = Views.Accounts.filter(_.userUuid === request.account.get.userUuid).map(_.equity).first.get val enoughFunds = validForm.offer < userEquity if (!enoughFunds) { Redirect(routes.Sale.item(itemUuid)) .flashing("error" -> "You are too poor!") } else if (!offersEnough) { Redirect(routes.Sale.item(itemUuid)) .flashing("error" -> "Please offer more.") } else { Tables.Bids += new Tables.Bid( itemUuid = itemUuid, userUuid = request.account.get.userUuid.get, bidDate = currentTimestamp, offer = validForm.offer ) Redirect(routes.Sale.item(itemUuid)) .flashing("success" -> "Thanks!") } } ) } } } } }