Adds createFromCart and order.completed subscribers
This commit is contained in:
@@ -12,19 +12,31 @@ export default async (req, res) => {
|
||||
|
||||
const paymentIntent = event.data.object
|
||||
|
||||
const orderService = req.scope.resolve("orderService")
|
||||
|
||||
// handle payment intent events
|
||||
switch (event.type) {
|
||||
case "payment_intent.succeeded":
|
||||
const cartId = paymentIntent.metadata.cart_id
|
||||
const order = await orderService.retrieveByCartId(cartId)
|
||||
|
||||
await orderService.update(order._id, {
|
||||
payment_status: "captured",
|
||||
})
|
||||
break
|
||||
case "payment_intent.canceled":
|
||||
break
|
||||
case "payment_intent.created":
|
||||
case "payment_intent.cancelled":
|
||||
const cartId = paymentIntent.metadata.cart_id
|
||||
const order = await orderService.retrieveByCartId(cartId)
|
||||
|
||||
await orderService.update(order._id, {
|
||||
status: "cancelled",
|
||||
})
|
||||
break
|
||||
case "payment_intent.payment_failed":
|
||||
// TODO: Not implemented yet
|
||||
break
|
||||
case "payment_intent.amount_capturable_updated":
|
||||
break
|
||||
case "payment_intent.processing":
|
||||
// TODO: Not implemented yet
|
||||
break
|
||||
default:
|
||||
res.status(400)
|
||||
|
||||
@@ -104,6 +104,8 @@ class StripeProviderService extends PaymentService {
|
||||
customer: stripeCustomerId,
|
||||
amount: amount * 100, // Stripe amount is in cents
|
||||
currency: currency_code,
|
||||
capture_method: "manual",
|
||||
metadata: { cart_id: cart._id },
|
||||
})
|
||||
|
||||
return paymentIntent
|
||||
|
||||
@@ -10,13 +10,14 @@ class CartSubscriber {
|
||||
this.stripeProviderService_ = stripeProviderService
|
||||
this.eventBus_ = eventBusService
|
||||
|
||||
this.eventBus_.subscribe("cart.created", (data) => {
|
||||
console.log(data)
|
||||
})
|
||||
|
||||
this.eventBus_.subscribe("cart.customer_updated", async (cart) => {
|
||||
await this.onCustomerUpdated(cart)
|
||||
})
|
||||
|
||||
this.eventBus_.subscribe("order.completed", async (order) => {
|
||||
const paymentData = order.payment_method.data
|
||||
await this.stripeProviderService_.capturePayment(paymentData)
|
||||
})
|
||||
}
|
||||
|
||||
async onCustomerUpdated(cart) {
|
||||
|
||||
@@ -7,6 +7,10 @@ class OrderSubscriber {
|
||||
this.eventBus_.subscribe("order.placed", async (order) => {
|
||||
await this.economicService_.draftEconomicInvoice(order)
|
||||
})
|
||||
|
||||
this.eventBus_.subscribe("order.completed", async (order) => {
|
||||
await this.economicService_.bookEconomicInvoice(order._id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export default async (req, res) => {
|
||||
const orderService = req.scope.resolve("orderService")
|
||||
|
||||
const cart = await cartService.retrieve(value.cartId)
|
||||
let order = await orderService.create(cart)
|
||||
let order = await orderService.createFromCart(cart)
|
||||
order = await orderService.decorate(order, [
|
||||
"status",
|
||||
"fulfillment_status",
|
||||
|
||||
@@ -63,6 +63,9 @@ export const orders = {
|
||||
fulfillment_status: "not_fulfilled",
|
||||
payment_status: "awaiting",
|
||||
status: "pending",
|
||||
metadata: {
|
||||
cart_id: IdMap.getId("test-cart"),
|
||||
},
|
||||
},
|
||||
processedOrder: {
|
||||
_id: IdMap.getId("processed-order"),
|
||||
@@ -237,6 +240,9 @@ export const OrderModelMock = {
|
||||
orders.orderToRefund.payment_status = "captured"
|
||||
return Promise.resolve(orders.orderToRefund)
|
||||
}
|
||||
if (query.metadata.cart_id === IdMap.getId("test-cart")) {
|
||||
return Promise.resolve(orders.testOrder)
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { OrderModelMock, orders } from "../../models/__mocks__/order"
|
||||
import { carts } from "../../models/__mocks__/cart"
|
||||
import OrderService from "../order"
|
||||
import { PaymentProviderServiceMock } from "../__mocks__/payment-provider"
|
||||
import { FulfillmentProviderServiceMock } from "../__mocks__/fulfillment-provider"
|
||||
@@ -30,6 +31,27 @@ describe("OrderService", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("createFromCart", () => {
|
||||
const orderService = new OrderService({
|
||||
orderModel: OrderModelMock,
|
||||
eventBusService: EventBusServiceMock,
|
||||
})
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it("calls order model functions", async () => {
|
||||
await orderService.createFromCart(carts.completeCart)
|
||||
|
||||
expect(OrderModelMock.create).toHaveBeenCalledTimes(1)
|
||||
expect(OrderModelMock.create).toHaveBeenCalledWith({
|
||||
...carts.completeCart,
|
||||
metadata: { cart_id: carts.completeCart._id },
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieve", () => {
|
||||
let result
|
||||
const orderService = new OrderService({
|
||||
@@ -53,6 +75,29 @@ describe("OrderService", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("retrieveByCartId", () => {
|
||||
let result
|
||||
const orderService = new OrderService({
|
||||
orderModel: OrderModelMock,
|
||||
})
|
||||
|
||||
beforeAll(async () => {
|
||||
jest.clearAllMocks()
|
||||
result = await orderService.retrieveByCartId(IdMap.getId("test-cart"))
|
||||
})
|
||||
|
||||
it("calls order model functions", async () => {
|
||||
expect(OrderModelMock.findOne).toHaveBeenCalledTimes(1)
|
||||
expect(OrderModelMock.findOne).toHaveBeenCalledWith({
|
||||
metadata: { cart_id: IdMap.getId("test-cart") },
|
||||
})
|
||||
})
|
||||
|
||||
it("returns correct order", async () => {
|
||||
expect(result._id).toEqual(IdMap.getId("test-order"))
|
||||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
const orderService = new OrderService({
|
||||
orderModel: OrderModelMock,
|
||||
|
||||
@@ -153,6 +153,27 @@ class OrderService extends BaseService {
|
||||
return order
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an order by cart id.
|
||||
* @param {string} cartId - cart id to find order
|
||||
* @return {Promise<Order>} the order document
|
||||
*/
|
||||
async retrieveByCartId(cartId) {
|
||||
const order = await this.orderModel_
|
||||
.findOne({ metadata: { cart_id: cartId } })
|
||||
.catch(err => {
|
||||
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
|
||||
})
|
||||
|
||||
if (!order) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
`Order with cart id ${cartId} was not found`
|
||||
)
|
||||
}
|
||||
return order
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} selector - the query object for find
|
||||
* @return {Promise} the result of the find operation
|
||||
@@ -161,6 +182,24 @@ class OrderService extends BaseService {
|
||||
return this.orderModel_.find(selector)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an order from a cart
|
||||
* @param {object} order - the order to create
|
||||
* @return {Promise} resolves to the creation result.
|
||||
*/
|
||||
async createFromCart(cart) {
|
||||
return this.orderModel_
|
||||
.create({ ...cart, metadata: { cart_id: cart._id } })
|
||||
.then(result => {
|
||||
// Notify subscribers
|
||||
this.eventBus_.emit(OrderService.Events.PLACED, result)
|
||||
return result
|
||||
})
|
||||
.catch(err => {
|
||||
throw new MedusaError(MedusaError.Types.DB_ERROR, err.message)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an order
|
||||
* @param {object} order - the order to create
|
||||
|
||||
Reference in New Issue
Block a user