-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: request order transfer storefront API
- Loading branch information
Showing
5 changed files
with
207 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { medusaIntegrationTestRunner } from "@medusajs/test-utils" | ||
import { Modules } from "@medusajs/utils" | ||
import { | ||
adminHeaders, | ||
createAdminUser, | ||
|
@@ -11,46 +12,47 @@ jest.setTimeout(300000) | |
|
||
medusaIntegrationTestRunner({ | ||
testSuite: ({ dbConnection, getContainer, api }) => { | ||
let order | ||
let customer | ||
let user | ||
let storeHeaders | ||
describe("Transfer Order flow (Admin)", () => { | ||
let order | ||
let customer | ||
let user | ||
let storeHeaders | ||
|
||
beforeEach(async () => { | ||
const container = getContainer() | ||
beforeEach(async () => { | ||
const container = getContainer() | ||
|
||
user = (await createAdminUser(dbConnection, adminHeaders, container)).user | ||
const publishableKey = await generatePublishableKey(container) | ||
storeHeaders = generateStoreHeaders({ publishableKey }) | ||
user = (await createAdminUser(dbConnection, adminHeaders, container)) | ||
.user | ||
const publishableKey = await generatePublishableKey(container) | ||
storeHeaders = generateStoreHeaders({ publishableKey }) | ||
|
||
const seeders = await createOrderSeeder({ api, container }) | ||
const seeders = await createOrderSeeder({ api, container }) | ||
|
||
const registeredCustomerToken = ( | ||
await api.post("/auth/customer/emailpass/register", { | ||
email: "[email protected]", | ||
password: "password", | ||
}) | ||
).data.token | ||
|
||
customer = ( | ||
await api.post( | ||
"/store/customers", | ||
{ | ||
const registeredCustomerToken = ( | ||
await api.post("/auth/customer/emailpass/register", { | ||
email: "[email protected]", | ||
}, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${registeredCustomerToken}`, | ||
...storeHeaders.headers, | ||
password: "password", | ||
}) | ||
).data.token | ||
|
||
customer = ( | ||
await api.post( | ||
"/store/customers", | ||
{ | ||
email: "[email protected]", | ||
}, | ||
} | ||
) | ||
).data.customer | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${registeredCustomerToken}`, | ||
...storeHeaders.headers, | ||
}, | ||
} | ||
) | ||
).data.customer | ||
|
||
order = seeders.order | ||
}) | ||
order = seeders.order | ||
}) | ||
|
||
describe("Transfer Order flow", () => { | ||
it("should pass order transfer flow from admin successfully", async () => { | ||
// 1. Admin requests order transfer for a customer with an account | ||
await api.post( | ||
|
@@ -229,5 +231,119 @@ medusaIntegrationTestRunner({ | |
) | ||
}) | ||
}) | ||
|
||
describe("Transfer Order flow (Admin)", () => { | ||
let order | ||
let customer | ||
let storeHeaders | ||
let signInToken | ||
|
||
let orderModule | ||
|
||
beforeEach(async () => { | ||
const container = getContainer() | ||
|
||
orderModule = await container.resolve(Modules.ORDER) | ||
|
||
const publishableKey = await generatePublishableKey(container) | ||
storeHeaders = generateStoreHeaders({ publishableKey }) | ||
|
||
const seeders = await createOrderSeeder({ api, container }) | ||
|
||
const registeredCustomerToken = ( | ||
await api.post("/auth/customer/emailpass/register", { | ||
email: "[email protected]", | ||
password: "password", | ||
}) | ||
).data.token | ||
|
||
customer = ( | ||
await api.post( | ||
"/store/customers", | ||
{ | ||
email: "[email protected]", | ||
}, | ||
{ | ||
headers: { | ||
Authorization: `Bearer ${registeredCustomerToken}`, | ||
...storeHeaders.headers, | ||
}, | ||
} | ||
) | ||
).data.customer | ||
|
||
signInToken = ( | ||
await api.post("/auth/customer/emailpass", { | ||
email: "[email protected]", | ||
password: "password", | ||
}) | ||
).data.token | ||
|
||
order = seeders.order | ||
}) | ||
|
||
it("should pass order transfer flow from storefront successfully", async () => { | ||
// 1. Customer requests order transfer | ||
const storeOrder = ( | ||
await api.post( | ||
`/store/orders/${order.id}/transfer/request?fields=+email,+customer_id`, | ||
{}, | ||
{ | ||
headers: { | ||
authorization: `Bearer ${signInToken}`, | ||
...storeHeaders.headers, | ||
}, | ||
} | ||
) | ||
).data.order | ||
|
||
// 2. Order still belongs to the guest customer since the transfer hasn't been accepted yet | ||
expect(storeOrder.email).toEqual("[email protected]") | ||
expect(storeOrder.customer_id).not.toEqual(customer.id) | ||
|
||
const orderChanges = await orderModule.listOrderChanges( | ||
{ order_id: order.id }, | ||
{ relations: ["actions"] } | ||
) | ||
|
||
expect(orderChanges.length).toEqual(1) | ||
expect(orderChanges[0]).toEqual( | ||
expect.objectContaining({ | ||
change_type: "transfer", | ||
status: "requested", | ||
requested_by: customer.id, | ||
created_by: customer.id, | ||
confirmed_by: null, | ||
confirmed_at: null, | ||
declined_by: null, | ||
actions: expect.arrayContaining([ | ||
expect.objectContaining({ | ||
version: 2, | ||
action: "TRANSFER_CUSTOMER", | ||
reference: "customer", | ||
reference_id: customer.id, | ||
details: expect.objectContaining({ | ||
token: expect.any(String), | ||
original_email: "[email protected]", | ||
}), | ||
}), | ||
]), | ||
}) | ||
) | ||
|
||
// 3. Guest customer who received the token accepts the transfer | ||
const finalOrder = ( | ||
await api.post( | ||
`/store/orders/${order.id}/transfer/accept?fields=+email,+customer_id`, | ||
{ token: orderChanges[0].actions[0].details.token }, | ||
storeHeaders | ||
) | ||
).data.order | ||
|
||
expect(finalOrder.email).toEqual("[email protected]") | ||
// 4. Customer account is now associated with the order (email on the order is still as original, guest email) | ||
expect(finalOrder.customer_id).toEqual(customer.id) | ||
}) | ||
}) | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
36 changes: 36 additions & 0 deletions
36
packages/medusa/src/api/store/orders/[id]/transfer/request/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import { | ||
getOrderDetailWorkflow, | ||
requestOrderTransferWorkflow, | ||
} from "@medusajs/core-flows" | ||
import { | ||
AuthenticatedMedusaRequest, | ||
MedusaResponse, | ||
} from "@medusajs/framework/http" | ||
import { HttpTypes } from "@medusajs/framework/types" | ||
import { StoreRequestOrderTransferType } from "../../../validators" | ||
|
||
export const POST = async ( | ||
req: AuthenticatedMedusaRequest<StoreRequestOrderTransferType>, | ||
res: MedusaResponse<HttpTypes.StoreOrderResponse> | ||
) => { | ||
const orderId = req.params.id | ||
const customerId = req.auth_context.actor_id | ||
|
||
await requestOrderTransferWorkflow(req.scope).run({ | ||
input: { | ||
order_id: orderId, | ||
customer_id: customerId, | ||
logged_in_user: customerId, | ||
description: req.validatedBody.description, | ||
}, | ||
}) | ||
|
||
const { result } = await getOrderDetailWorkflow(req.scope).run({ | ||
input: { | ||
fields: req.remoteQueryConfig.fields, | ||
order_id: orderId, | ||
}, | ||
}) | ||
|
||
res.status(200).json({ order: result as HttpTypes.StoreOrder }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters