Merge branch 'master' of github.com:medusajs/medusa
This commit is contained in:
@@ -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,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 }
|
||||||
|
|||||||
@@ -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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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(
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user