package dao import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider} import slick.jdbc.PostgresProfile import slick.jdbc.PostgresProfile.api.* import java.time.Instant import javax.inject.Inject import scala.concurrent.{ExecutionContext, Future} import scala.util.Random import models.{Auction, AuctionStatus, User} import schemas.Auctions import schemas.given class AuctionsDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider)(implicit val ec: ExecutionContext) extends HasDatabaseConfigProvider[PostgresProfile] { def list_available(user: User): Future[Seq[Auction]] = { db.run(availableScope(user).result) } def showAvailable(user: User, id: Long): Future[Option[Auction]] = { db.run { availableScope(user).filter(_.id === id).take(1).result.headOption } } def list_created_by(user: User): Future[Seq[Auction]] = { db.run(Auctions.filter(_.authorId === user.id).result) } def create(name: String, startingPrice: BigDecimal, author: User): Future[Auction] = { val auction = Auction( id = None, name = name, gid = Random.alphanumeric.take(24).mkString, status = AuctionStatus.Created, authorId = author.id.get, startingPrice = startingPrice, currentBid = None, currentBidderId = None, currentBidAt = None, createdAt = Instant.now() ) create(auction) } def create(auction: Auction) : Future[Auction] = { db.run((Auctions returning Auctions) += auction) } def changeStatus(auctionId: Long, status: AuctionStatus): Future[Boolean] = { db.run(Auctions.filter(_.id === auctionId).map(_.status).update(status)) .map(_ == 1) } def find_by_gid(gid: String): Future[Option[Auction]] = { db.run(Auctions.filter(_.gid === gid).take(1).result.headOption) } def newBid(auction: Auction, bidder: User, bid: BigDecimal, timestamp: Instant): Future[Option[Auction]] = { db.run { Auctions.filter(_.id === auction.id.get).map{ it => (it.currentBid, it.currentBidAt, it.currentBidderId) } .update((Some(bid), Some(timestamp), Some(bidder.id.get))) .andThen { Auctions.filter(_.id === auction.id.get).result.headOption } .transactionally } } private def availableScope(user: User) = { Auctions.filter(row => (row.status === AuctionStatus.Ready) && (row.authorId =!= user.id.get)) } }