diff --git a/phoenix-scala/core/app/core/db/package.scala b/phoenix-scala/core/app/core/db/package.scala index b3acfd16db..6eb13a45b4 100644 --- a/phoenix-scala/core/app/core/db/package.scala +++ b/phoenix-scala/core/app/core/db/package.scala @@ -336,17 +336,17 @@ package object db { implicit class EnrichedDBIOpt[R](val dbio: DBIO[Option[R]]) extends AnyVal { - def findOrCreate(r: DbResultT[R])(implicit ec: EC): DbResultT[R] = + def findOrCreate(createAction: ⇒ DbResultT[R])(implicit ec: EC): DbResultT[R] = dbio.dbresult.flatMap { case Some(model) ⇒ DbResultT.good(model) - case None ⇒ r + case None ⇒ createAction } // Last item in tuple determines if cart was created or not - def findOrCreateExtended(r: DbResultT[R])(implicit ec: EC): DbResultT[(R, FoundOrCreated)] = + def findOrCreateExtended(createAction: ⇒ DbResultT[R])(implicit ec: EC): DbResultT[(R, FoundOrCreated)] = dbio.dbresult.flatMap { case Some(model) ⇒ DbResultT.good((model, Found)) - case _ ⇒ r.map(result ⇒ (result, Created)) + case _ ⇒ createAction.map(result ⇒ (result, Created)) } def mustFindOr(notFoundFailure: Failure)(implicit ec: EC): DbResultT[R] = diff --git a/phoenix-scala/phoenix/app/phoenix/models/cord/OrderShippingAddress.scala b/phoenix-scala/phoenix/app/phoenix/models/cord/OrderShippingAddress.scala index 7866ee50ea..08b897e1d7 100644 --- a/phoenix-scala/phoenix/app/phoenix/models/cord/OrderShippingAddress.scala +++ b/phoenix-scala/phoenix/app/phoenix/models/cord/OrderShippingAddress.scala @@ -87,7 +87,7 @@ object OrderShippingAddresses import scope._ - def copyFromAddress(address: Address, cordRef: String)(implicit ec: EC): DbResultT[OrderShippingAddress] = + def createFromAddress(address: Address, cordRef: String)(implicit ec: EC): DbResultT[OrderShippingAddress] = create(OrderShippingAddress.buildFromAddress(address).copy(cordRef = cordRef)) def findByOrderRef(cordRef: String): QuerySeq = @@ -106,6 +106,14 @@ object OrderShippingAddresses shippingAddresses ← q regions ← Regions if regions.id === shippingAddresses.regionId } yield (shippingAddresses, regions) + + def withCustomerAddress( + accountId: Int): Query[(OrderShippingAddresses, Addresses), (OrderShippingAddress, Address), Seq] = + for { + shippingAddresses ← q + adr ← Addresses + if adr.accountId === accountId && adr.address1 === shippingAddresses.address1 && adr.name === shippingAddresses.name + } yield (shippingAddresses, adr) // FIXME when we have fk to Address @aafa } } } diff --git a/phoenix-scala/phoenix/app/phoenix/routes/Customer.scala b/phoenix-scala/phoenix/app/phoenix/routes/Customer.scala index 51d68e8da7..52988a576f 100644 --- a/phoenix-scala/phoenix/app/phoenix/routes/Customer.scala +++ b/phoenix-scala/phoenix/app/phoenix/routes/Customer.scala @@ -144,6 +144,11 @@ object Customer { CartShippingAddressUpdater.createShippingAddressFromPayload(auth.model, payload) } } ~ + (put & pathEnd & entity(as[CreateAddressPayload])) { payload ⇒ + mutateOrFailures { + CartShippingAddressUpdater.createOrUpdateShippingAddress(auth.model, payload) + } + } ~ (delete & pathEnd) { deleteOrFailures { CartShippingAddressUpdater.removeShippingAddress(auth.model) diff --git a/phoenix-scala/phoenix/app/phoenix/routes/admin/CartRoutes.scala b/phoenix-scala/phoenix/app/phoenix/routes/admin/CartRoutes.scala index 32f412ad83..20516e1d64 100644 --- a/phoenix-scala/phoenix/app/phoenix/routes/admin/CartRoutes.scala +++ b/phoenix-scala/phoenix/app/phoenix/routes/admin/CartRoutes.scala @@ -153,6 +153,11 @@ object CartRoutes { Some(refNum)) } } ~ + (put & pathEnd & entity(as[CreateAddressPayload])) { payload ⇒ + mutateOrFailures { + CartShippingAddressUpdater.createOrUpdateShippingAddress(auth.model, payload, Some(refNum)) + } + } ~ (delete & pathEnd) { mutateOrFailures { CartShippingAddressUpdater.removeShippingAddress(auth.model, Some(refNum)) diff --git a/phoenix-scala/phoenix/app/phoenix/services/carts/CartShippingAddressUpdater.scala b/phoenix-scala/phoenix/app/phoenix/services/carts/CartShippingAddressUpdater.scala index 8ee8e5c0fb..bcc9da22b8 100644 --- a/phoenix-scala/phoenix/app/phoenix/services/carts/CartShippingAddressUpdater.scala +++ b/phoenix-scala/phoenix/app/phoenix/services/carts/CartShippingAddressUpdater.scala @@ -14,6 +14,8 @@ import phoenix.services.{CartValidator, LogActivity} import slick.jdbc.PostgresProfile.api._ import phoenix.utils.aliases._ import core.db._ +import cats.implicits._ +import OrderShippingAddresses.scope._ object CartShippingAddressUpdater { @@ -23,6 +25,13 @@ object CartShippingAddressUpdater { def mustFindShipAddressForCart(cart: Cart)(implicit ec: EC): DbResultT[OrderShippingAddress] = OrderShippingAddresses.findByOrderRef(cart.refNum).mustFindOneOr(NoShipAddress(cart.refNum)) + private def createShippingAddress(cart: Cart, payload: CreateAddressPayload)( + implicit ec: EC): DbResultT[(OrderShippingAddress, Address)] = + for { + newAddress ← * <~ Addresses.create(Address.fromPayload(payload, cart.accountId)) + shippingAddress ← * <~ OrderShippingAddresses.createFromAddress(newAddress, cart.refNum) + } yield (shippingAddress, newAddress) + def createShippingAddressFromAddressId(originator: User, addressId: Int, refNum: Option[String] = None)( implicit ec: EC, db: DB, @@ -34,7 +43,7 @@ object CartShippingAddressUpdater { _ ← * <~ OrderShippingAddresses.findByOrderRef(cart.refNum).delete (address, _) = addAndReg _ ← * <~ address.mustBelongToAccount(cart.accountId) - shipAddress ← * <~ OrderShippingAddresses.copyFromAddress(address, cart.refNum) + shipAddress ← * <~ OrderShippingAddresses.createFromAddress(address, cart.refNum) region ← * <~ Regions.mustFindById404(shipAddress.regionId) validated ← * <~ CartValidator(cart).validate() response ← * <~ CartResponse.buildRefreshed(cart) @@ -53,7 +62,7 @@ object CartShippingAddressUpdater { cart ← * <~ getCartByOriginator(originator, refNum) newAddress ← * <~ Addresses.create(Address.fromPayload(payload, cart.accountId)) _ ← * <~ OrderShippingAddresses.findByOrderRef(cart.refNum).delete - shipAddress ← * <~ OrderShippingAddresses.copyFromAddress(newAddress, cart.refNum) + shipAddress ← * <~ OrderShippingAddresses.createFromAddress(newAddress, cart.refNum) region ← * <~ Regions.mustFindById404(shipAddress.regionId) validated ← * <~ CartValidator(cart).validate() response ← * <~ CartResponse.buildRefreshed(cart) @@ -80,6 +89,40 @@ object CartShippingAddressUpdater { .orderShippingAddressUpdated(originator, response, buildFromOrder(shipAddress, region)) } yield TheResponse.validated(response, validated) + // FIXME !!! @aafa + def createOrUpdateShippingAddress(originator: User, + payload: CreateAddressPayload, + refNum: Option[String] = None)( + implicit ec: EC, + db: DB, + ac: AC, + ctx: OC): DbResultT[TheResponse[CartResponse]] = + for { + cart ← * <~ getCartByOriginator(originator, refNum) + + shippingTuple ← * <~ OrderShippingAddresses + .findByOrderRef(cart.refNum) + .withCustomerAddress(cart.accountId) + .one + .findOrCreateExtended(createShippingAddress(cart, payload)) + + ((shippingAddress, address), foundOrCreated) = shippingTuple + + _ ← * <~ doOrMeh( + foundOrCreated == Found, + for { + _ ← * <~ Addresses.update(address, Address.fromPayload(payload, cart.accountId)) + } yield DbResultT.unit + ) + + region ← * <~ Regions.mustFindById404(shippingAddress.regionId) + validated ← * <~ CartValidator(cart).validate() + response ← * <~ CartResponse.buildRefreshed(cart) + _ ← * <~ LogActivity().orderShippingAddressUpdated(originator, + response, + buildFromOrder(shippingAddress, region)) + } yield TheResponse.validated(response, validated) + def removeShippingAddress(originator: User, refNum: Option[String] = None)( implicit ec: EC, db: DB, diff --git a/phoenix-scala/phoenix/test/integration/AddressesIntegrationTest.scala b/phoenix-scala/phoenix/test/integration/AddressesIntegrationTest.scala index 2392fabe75..ad680bbb0f 100644 --- a/phoenix-scala/phoenix/test/integration/AddressesIntegrationTest.scala +++ b/phoenix-scala/phoenix/test/integration/AddressesIntegrationTest.scala @@ -246,7 +246,7 @@ class AddressesIntegrationTest trait ShippingAddressFixture extends EmptyCartWithShipAddress_Baked trait NoDefaultAddressFixture extends CustomerAddress_Baked with EmptyCustomerCart_Baked { - val shippingAddress = OrderShippingAddresses.copyFromAddress(address, cart.refNum).gimme + val shippingAddress = OrderShippingAddresses.createFromAddress(address, cart.refNum).gimme } trait AddressFixture { diff --git a/phoenix-scala/phoenix/test/integration/CartValidatorIntegrationTest.scala b/phoenix-scala/phoenix/test/integration/CartValidatorIntegrationTest.scala index bee3a6181f..20928752f4 100644 --- a/phoenix-scala/phoenix/test/integration/CartValidatorIntegrationTest.scala +++ b/phoenix-scala/phoenix/test/integration/CartValidatorIntegrationTest.scala @@ -147,7 +147,7 @@ class CartValidatorIntegrationTest trait ShippingMethodFixture extends EmptyCustomerCart_Baked { val (shipMethod) = (for { address ← * <~ Addresses.create(Factories.address.copy(accountId = customer.accountId, regionId = 4129)) - _ ← * <~ OrderShippingAddresses.copyFromAddress(address = address, cordRef = cart.refNum) + _ ← * <~ OrderShippingAddresses.createFromAddress(address = address, cordRef = cart.refNum) shipMethod ← * <~ ShippingMethods.create(Factories.shippingMethods.head) } yield shipMethod).gimme val refNum = cart.refNum diff --git a/phoenix-scala/phoenix/test/integration/ShippingMethodsIntegrationTest.scala b/phoenix-scala/phoenix/test/integration/ShippingMethodsIntegrationTest.scala index b9430631d4..af76c5032b 100644 --- a/phoenix-scala/phoenix/test/integration/ShippingMethodsIntegrationTest.scala +++ b/phoenix-scala/phoenix/test/integration/ShippingMethodsIntegrationTest.scala @@ -174,7 +174,7 @@ class ShippingMethodsIntegrationTest productContext ← * <~ ObjectContexts.mustFindById404(SimpleContext.id) address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = californiaId)) - shipAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, cordRef = cart.refNum) + shipAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, cordRef = cart.refNum) product ← * <~ Mvp.insertProduct(productContext.id, Factories.products.head.copy(title = "Donkey", price = 27)) _ ← * <~ CartLineItems.create(CartLineItem(cordRef = cart.refNum, skuId = product.skuId)) diff --git a/phoenix-scala/phoenix/test/integration/services/CheckoutTest.scala b/phoenix-scala/phoenix/test/integration/services/CheckoutTest.scala index a2effda832..f9706155ec 100644 --- a/phoenix-scala/phoenix/test/integration/services/CheckoutTest.scala +++ b/phoenix-scala/phoenix/test/integration/services/CheckoutTest.scala @@ -176,7 +176,7 @@ class CheckoutTest c ← * <~ Carts.refresh(cart) _ ← * <~ OrderShippingMethods.create(OrderShippingMethod.build(cart.refNum, shipMethod)) - _ ← * <~ OrderShippingAddresses.copyFromAddress(address = address, cordRef = cart.refNum) + _ ← * <~ OrderShippingAddresses.createFromAddress(address = address, cordRef = cart.refNum) gcIds ← * <~ generateGiftCards(gcData.map(_.cardAmount)) scIds ← * <~ generateStoreCredits(scData.map(_.cardAmount)) @@ -249,7 +249,7 @@ class CheckoutTest override val cart = super.cart.copy(grandTotal = 1000) (for { _ ← * <~ OrderShippingMethods.create(OrderShippingMethod.build(cart.refNum, shipMethod)) - _ ← * <~ OrderShippingAddresses.copyFromAddress(address = address, cordRef = cart.refNum) + _ ← * <~ OrderShippingAddresses.createFromAddress(address = address, cordRef = cart.refNum) } yield {}).gimme } } diff --git a/phoenix-scala/phoenix/test/integration/services/ShippingManagerTest.scala b/phoenix-scala/phoenix/test/integration/services/ShippingManagerTest.scala index 1fc55dc1f2..1c16bc787d 100644 --- a/phoenix-scala/phoenix/test/integration/services/ShippingManagerTest.scala +++ b/phoenix-scala/phoenix/test/integration/services/ShippingManagerTest.scala @@ -46,7 +46,7 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit isDefaultShipping = false)) .gimme OrderShippingAddresses.filter(_.id === shippingAddress.id).delete.run().futureValue - OrderShippingAddresses.copyFromAddress(address = canada, cordRef = cart.refNum).gimme + OrderShippingAddresses.createFromAddress(address = canada, cordRef = cart.refNum).gimme val matchingMethods = getShippingMethodsForCart(cart.refNum).gimme matchingMethods.headOption.value.name must === (shippingMethod.adminDisplayName) @@ -77,8 +77,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, orderShippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = washingtonId)) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme val matchingMethods = getShippingMethodsForCart(cart.refNum).gimme @@ -89,8 +89,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, orderShippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = michiganId)) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme val matchingMethods = getShippingMethodsForCart(cart.refNum).gimme @@ -104,8 +104,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, orderShippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = washingtonId)) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme val matchingMethods = getShippingMethodsForCart(cart.refNum).gimme @@ -118,8 +118,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit Factories.address.copy(accountId = customer.accountId, regionId = washingtonId, address1 = "P.O. Box 1234")) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme val matchingMethods = getShippingMethodsForCart(cart.refNum).gimme @@ -132,8 +132,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit Factories.address.copy(accountId = customer.accountId, regionId = washingtonId, address2 = Some("P.O. Box 1234"))) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme val matchingMethods = getShippingMethodsForCart(cart.refNum).gimme @@ -162,7 +162,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, shippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = californiaId)) - shippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, cordRef = cart.refNum) + shippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, shippingAddress)).gimme } @@ -200,8 +201,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, orderShippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = californiaId)) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme } @@ -209,8 +210,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, orderShippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = washingtonId)) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme } @@ -218,8 +219,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit val (address, orderShippingAddress) = (for { address ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, regionId = michiganId)) - orderShippingAddress ← * <~ OrderShippingAddresses.copyFromAddress(address = address, - cordRef = cart.refNum) + orderShippingAddress ← * <~ OrderShippingAddresses.createFromAddress(address = address, + cordRef = cart.refNum) } yield (address, orderShippingAddress)).gimme } @@ -279,7 +280,7 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit cheapAddress ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, isDefaultShipping = false)) - _ ← * <~ OrderShippingAddresses.copyFromAddress(address = cheapAddress, cordRef = cheapCart.refNum) + _ ← * <~ OrderShippingAddresses.createFromAddress(address = cheapAddress, cordRef = cheapCart.refNum) account2 ← * <~ Accounts.create(Account()) customer2 ← * <~ Users.create( Factories.customer.copy(accountId = account2.id, email = "foo@bar.baz".some)) @@ -297,8 +298,8 @@ class ShippingManagerTest extends IntegrationTestBase with TestObjectContext wit CartLineItem(cordRef = expensiveCart.refNum, skuId = expensiveProduct.skuId)) expensiveAddress ← * <~ Addresses.create( Factories.address.copy(accountId = customer.accountId, isDefaultShipping = false)) - _ ← * <~ OrderShippingAddresses.copyFromAddress(address = expensiveAddress, - cordRef = expensiveCart.refNum) + _ ← * <~ OrderShippingAddresses.createFromAddress(address = expensiveAddress, + cordRef = expensiveCart.refNum) cheapCart ← * <~ CartTotaler.saveTotals(cheapCart) expensiveCart ← * <~ CartTotaler.saveTotals(expensiveCart)