Merge branch 'master' of github.com:medusajs/medusa

This commit is contained in:
Sebastian Rindom
2020-11-13 13:54:10 +01:00
6 changed files with 243 additions and 38 deletions
+11
View File
@@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.0.40](https://github.com/medusajs/medusa/compare/@medusajs/medusa@1.0.39...@medusajs/medusa@1.0.40) (2020-11-13)
### Features
* **medusa:** Adds shipped status to line items + Capture fails will give payment_status = requires_action ([6a3c545](https://github.com/medusajs/medusa/commit/6a3c5455371c33e47722c7ab433a48d1d9b5b511))
## [1.0.39](https://github.com/medusajs/medusa/compare/@medusajs/medusa@1.0.38...@medusajs/medusa@1.0.39) (2020-11-05) ## [1.0.39](https://github.com/medusajs/medusa/compare/@medusajs/medusa@1.0.38...@medusajs/medusa@1.0.39) (2020-11-05)
**Note:** Version bump only for package @medusajs/medusa **Note:** Version bump only for package @medusajs/medusa
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@medusajs/medusa", "name": "@medusajs/medusa",
"version": "1.0.39", "version": "1.0.40",
"description": "E-commerce for JAMstack", "description": "E-commerce for JAMstack",
"main": "dist/app.js", "main": "dist/app.js",
"repository": { "repository": {
@@ -368,6 +368,97 @@ export const orders = {
], ],
discounts: [], discounts: [],
}, },
shippedOrder: {
_id: IdMap.getId("shippedOrder"),
email: "oliver@test.dk",
billing_address: {
first_name: "Oli",
last_name: "Medusa",
address_1: "testaddress",
city: "LA",
country_code: "US",
postal_code: "90002",
},
shipping_address: {
first_name: "Oli",
last_name: "Medusa",
address_1: "testaddress",
city: "LA",
country_code: "US",
postal_code: "90002",
},
items: [
{
_id: IdMap.getId("existingLine"),
title: "merge line",
description: "This is a new line",
thumbnail: "test-img-yeah.com/thumb",
content: {
unit_price: 123,
variant: {
_id: IdMap.getId("can-cover"),
},
product: {
_id: IdMap.getId("validId"),
},
quantity: 1,
},
fulfilled_quantity: 10,
shipped_quantity: 0,
quantity: 10,
},
],
region_id: IdMap.getId("region-france"),
customer_id: IdMap.getId("test-customer"),
payment_method: {
provider_id: "default_provider",
},
shipping_methods: [
{
_id: IdMap.getId("expensiveShipping"),
name: "Expensive Shipping",
price: 100,
provider_id: "default_provider",
profile_id: IdMap.getId("default"),
data: {
extra: "hi",
},
},
],
fulfillments: [
{
_id: IdMap.getId("fulfillment"),
provider_id: "default_provider",
data: {},
items: [
{
_id: IdMap.getId("existingLine"),
content: {
product: {
_id: IdMap.getId("validId"),
},
quantity: 1,
unit_price: 123,
variant: {
_id: IdMap.getId("can-cover"),
},
},
description: "This is a new line",
fulfilled_quantity: 10,
quantity: 10,
thumbnail: "test-img-yeah.com/thumb",
title: "merge line",
},
],
},
],
fulfillment_status: "not_fulfilled",
payment_status: "awaiting",
status: "pending",
metadata: {
cart_id: IdMap.getId("test-cart"),
},
},
} }
export const OrderModelMock = { export const OrderModelMock = {
@@ -420,6 +511,9 @@ export const OrderModelMock = {
if (query.cart_id === IdMap.getId("test-cart")) { if (query.cart_id === IdMap.getId("test-cart")) {
return Promise.resolve(orders.testOrder) return Promise.resolve(orders.testOrder)
} }
if (query._id === IdMap.getId("shippedOrder")) {
return Promise.resolve(orders.shippedOrder)
}
return Promise.resolve(undefined) return Promise.resolve(undefined)
}), }),
} }
@@ -45,6 +45,7 @@ export default new mongoose.Schema(
fulfilled: { type: Boolean, default: false }, fulfilled: { type: Boolean, default: false },
fulfilled_quantity: { type: Number, default: 0 }, fulfilled_quantity: { type: Number, default: 0 },
returned_quantity: { type: Number, default: 0 }, returned_quantity: { type: Number, default: 0 },
shipped_quantity: { type: Number, default: 0 },
metadata: { type: mongoose.Schema.Types.Mixed, default: {} }, metadata: { type: mongoose.Schema.Types.Mixed, default: {} },
}, },
{ minimize: false } { minimize: false }
+57 -11
View File
@@ -509,7 +509,8 @@ describe("OrderService", () => {
}, },
quantity: 1, quantity: 1,
}, },
fulfilled_quantity: 0, fulfilled_quantity: 10,
fulfilled: true,
quantity: 10, quantity: 10,
}, },
], ],
@@ -1121,7 +1122,7 @@ describe("OrderService", () => {
it("calls order model functions", async () => { it("calls order model functions", async () => {
await orderService.createShipment( await orderService.createShipment(
IdMap.getId("test-order"), IdMap.getId("shippedOrder"),
IdMap.getId("fulfillment"), IdMap.getId("fulfillment"),
["1234", "2345"], ["1234", "2345"],
{} {}
@@ -1130,19 +1131,64 @@ describe("OrderService", () => {
expect(OrderModelMock.updateOne).toHaveBeenCalledTimes(1) expect(OrderModelMock.updateOne).toHaveBeenCalledTimes(1)
expect(OrderModelMock.updateOne).toHaveBeenCalledWith( expect(OrderModelMock.updateOne).toHaveBeenCalledWith(
{ {
_id: IdMap.getId("test-order"), _id: IdMap.getId("shippedOrder"),
"fulfillments._id": IdMap.getId("fulfillment"), "fulfillments._id": IdMap.getId("fulfillment"),
}, },
{ {
$set: { $set: {
"fulfillments.$": { "fulfillments.$": [
_id: IdMap.getId("fulfillment"), {
provider_id: "default_provider", _id: IdMap.getId("fulfillment"),
tracking_numbers: ["1234", "2345"], provider_id: "default_provider",
data: {}, tracking_numbers: ["1234", "2345"],
shipped_at: expect.anything(), data: {},
metadata: {}, items: [
}, {
_id: IdMap.getId("existingLine"),
content: {
product: {
_id: IdMap.getId("validId"),
},
quantity: 1,
unit_price: 123,
variant: {
_id: IdMap.getId("can-cover"),
},
},
description: "This is a new line",
fulfilled_quantity: 10,
shipped_quantity: 10,
quantity: 10,
thumbnail: "test-img-yeah.com/thumb",
title: "merge line",
},
],
shipped_at: expect.anything(),
metadata: {},
},
],
items: [
{
_id: IdMap.getId("existingLine"),
content: {
product: {
_id: IdMap.getId("validId"),
},
quantity: 1,
unit_price: 123,
variant: {
_id: IdMap.getId("can-cover"),
},
},
description: "This is a new line",
fulfilled_quantity: 10,
shipped_quantity: 10,
quantity: 10,
thumbnail: "test-img-yeah.com/thumb",
title: "merge line",
},
],
fulfillment_status: "shipped",
}, },
} }
) )
+77 -24
View File
@@ -6,6 +6,7 @@ class OrderService extends BaseService {
static Events = { static Events = {
GIFT_CARD_CREATED: "order.gift_card_created", GIFT_CARD_CREATED: "order.gift_card_created",
PAYMENT_CAPTURED: "order.payment_captured", PAYMENT_CAPTURED: "order.payment_captured",
PAYMENT_CAPTURE_FAILED: "order.payment_capture_failed",
SHIPMENT_CREATED: "order.shipment_created", SHIPMENT_CREATED: "order.shipment_created",
FULFILLMENT_CREATED: "order.fulfillment_created", FULFILLMENT_CREATED: "order.fulfillment_created",
RETURN_REQUESTED: "order.return_requested", RETURN_REQUESTED: "order.return_requested",
@@ -418,22 +419,39 @@ class OrderService extends BaseService {
async createShipment(orderId, fulfillmentId, trackingNumbers, metadata = {}) { async createShipment(orderId, fulfillmentId, trackingNumbers, metadata = {}) {
const order = await this.retrieve(orderId) const order = await this.retrieve(orderId)
const shipment = order.fulfillments.find(f => f._id.equals(fulfillmentId)) let shipment
if (!shipment) { const updated = order.fulfillments.map(f => {
throw new MedusaError( if (f._id.equals(fulfillmentId)) {
MedusaError.Types.NOT_FOUND, // For each item in the shipment, we set their status to shipped
`Could not find a fulfillment with the provided id` f.items.map(item => {
) const itemIdx = order.items.findIndex(el => el._id.equals(item._id))
} // Update item in order.items and in fullfillment.items to
// ensure consistency
if (item !== -1) {
item.shipped_quantity = item.quantity
order.items[itemIdx].shipped_quantity += item.quantity
}
})
shipment = {
...f,
tracking_numbers: trackingNumbers,
shipped_at: Date.now(),
metadata: {
...f.metadata,
...metadata,
},
}
return shipment
}
return f
})
const updated = { let fulfillmentStatus = "shipped"
...shipment, for (const item of order.items) {
tracking_numbers: trackingNumbers, if (item.quantity !== item.shipped_quantity) {
shipped_at: Date.now(), fulfillmentStatus = "partially_shipped"
metadata: { break
...shipment.metadata, }
...metadata,
},
} }
// Add the shipment to the order // Add the shipment to the order
@@ -441,7 +459,11 @@ class OrderService extends BaseService {
.updateOne( .updateOne(
{ _id: orderId, "fulfillments._id": fulfillmentId }, { _id: orderId, "fulfillments._id": fulfillmentId },
{ {
$set: { "fulfillments.$": updated }, $set: {
"fulfillments.$": updated,
items: order.items,
fulfillment_status: fulfillmentStatus,
},
} }
) )
.then(result => { .then(result => {
@@ -638,7 +660,26 @@ class OrderService extends BaseService {
provider_id provider_id
) )
await paymentProvider.capturePayment(data) try {
await paymentProvider.capturePayment(data)
} catch (error) {
return this.orderModel_
.updateOne(
{
_id: orderId,
},
{
$set: { payment_status: "requires_action" },
}
)
.then(result => {
this.eventBus_.emit(
OrderService.Events.PAYMENT_CAPTURE_FAILED,
result
)
return result
})
}
return this.orderModel_ return this.orderModel_
.updateOne( .updateOne(
@@ -705,12 +746,7 @@ class OrderService extends BaseService {
const { shipping_methods } = order const { shipping_methods } = order
// prepare update object const updateFields = {}
const updateFields = { fulfillment_status: "fulfilled" }
const completed = order.payment_status !== "awaiting"
if (completed) {
updateFields.status = "completed"
}
// partition order items to their dedicated shipping method // partition order items to their dedicated shipping method
const fulfillments = await this.partitionItems_(shipping_methods, lineItems) const fulfillments = await this.partitionItems_(shipping_methods, lineItems)
@@ -729,6 +765,14 @@ class OrderService extends BaseService {
return res return res
}) })
method.items = method.items.map(el => {
return {
...el,
fulfilled_quantity: el.quantity,
fulfilled: true,
}
})
return { return {
provider_id: method.provider_id, provider_id: method.provider_id,
items: method.items, items: method.items,
@@ -745,13 +789,22 @@ class OrderService extends BaseService {
return { return {
...i, ...i,
fulfilled: i.quantity === ful.quantity, fulfilled: i.quantity === ful.quantity,
fulfilled_quantity: ful.quantity, fulfilled_quantity: i.fulfilled_quantity + ful.quantity,
} }
} }
return i return i
}) })
updateFields.fulfillment_status = "fulfilled"
for (const el of updateFields.items) {
if (el.quantity !== el.fulfilled_quantity) {
updateFields.fulfillment_status = "partially_fulfilled"
break
}
}
return this.orderModel_ return this.orderModel_
.updateOne( .updateOne(
{ {