const path = require("path") const setupServer = require("../../../environment-helpers/setup-server") const { useApi } = require("../../../environment-helpers/use-api") const { initDb, useDb } = require("../../../environment-helpers/use-db") const adminSeeder = require("../../../helpers/admin-seeder") const { simpleOrderFactory, simpleShippingOptionFactory, simplePaymentFactory, simpleProductFactory, } = require("../../../factories") describe("Claims", () => { let medusaProcess let dbConnection const doAfterEach = async () => { const db = useDb() return await db.teardown() } beforeAll(async () => { const cwd = path.resolve(path.join(__dirname, "..", "..")) dbConnection = await initDb({ cwd }) medusaProcess = await setupServer({ cwd }) }) afterAll(async () => { const db = useDb() await db.shutdown() medusaProcess.kill() }) afterEach(async () => { return await doAfterEach() }) test("creates a refund claim with custom refund amount", async () => { await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const api = useApi() const response = await api.post( `/admin/orders/${order.id}/claims`, { type: "refund", refund_amount: 1000, claim_items: [ { item_id: "test-item", reason: "missing_item", quantity: 1, }, ], }, { headers: { "x-medusa-access-token": "test_token", }, } ) expect(response.status).toEqual(200) expect(response.data.order.claims[0]).toEqual( expect.objectContaining({ order_id: expect.any(String), refund_amount: 1000, claim_items: expect.arrayContaining([ expect.objectContaining({ item: expect.any(Object), item_id: "test-item", quantity: 1, }), ]), }) ) }) test("creates a refund claim", async () => { await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const api = useApi() const response = await api.post( `/admin/orders/${order.id}/claims`, { type: "refund", claim_items: [ { item_id: "test-item", reason: "missing_item", quantity: 1, }, ], }, { headers: { "x-medusa-access-token": "test_token", }, } ) expect(response.status).toEqual(200) expect(response.data.order.claims[0]).toEqual( expect.objectContaining({ order_id: expect.any(String), refund_amount: 1200, claim_items: expect.arrayContaining([ expect.objectContaining({ item: expect.any(Object), item_id: "test-item", quantity: 1, }), ]), }) ) }) test("creates a refund claim + return", async () => { await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const api = useApi() const response = await api.post( `/admin/orders/${order.id}/claims`, { type: "refund", claim_items: [ { item_id: "test-item", reason: "missing_item", quantity: 1, }, ], return_shipping: { price: 0, }, }, { headers: { "x-medusa-access-token": "test_token", }, } ) const claim = response.data.order.claims[0] const refund = response.data.order.refunds[0] const returnOrder = response.data.order.returns[0] expect(response.status).toEqual(200) expect(claim.refund_amount).toEqual(1200) expect(refund.amount).toEqual(1200) expect(returnOrder.refund_amount).toEqual(1200) }) test("creates a refund claim + return with a custom amount", async () => { await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const api = useApi() const response = await api.post( `/admin/orders/${order.id}/claims`, { type: "refund", refund_amount: 500, claim_items: [ { item_id: "test-item", reason: "missing_item", quantity: 1, }, ], return_shipping: { price: 0, }, }, { headers: { "x-medusa-access-token": "test_token", }, } ) const claim = response.data.order.claims[0] const refund = response.data.order.refunds[0] const returnOrder = response.data.order.returns[0] expect(response.status).toEqual(200) expect(claim.refund_amount).toEqual(500) expect(refund.amount).toEqual(500) expect(returnOrder.refund_amount).toEqual(500) }) test("creates a replace claim", async () => { await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const api = useApi() const response = await api.post( `/admin/orders/${order.id}/claims`, { type: "replace", additional_items: [{ variant_id: "test-variant", quantity: 1 }], claim_items: [ { item_id: "test-item", reason: "missing_item", quantity: 1, }, ], }, { headers: { "x-medusa-access-token": "test_token", }, } ) expect(response.status).toEqual(200) expect(response.data.order.claims[0]).toEqual( expect.objectContaining({ id: expect.stringMatching(/^claim_*/), order_id: expect.any(String), additional_items: expect.arrayContaining([ expect.objectContaining({ id: expect.stringMatching(/^item_*/), claim_order_id: expect.stringMatching(/^claim_*/), variant: expect.objectContaining({ id: "test-variant" }), tax_lines: expect.arrayContaining([ expect.objectContaining({ id: expect.stringMatching(/^litl_*/), item_id: expect.stringMatching(/^item_*/), rate: 12.5, }), ]), }), ]), claim_items: expect.arrayContaining([ expect.objectContaining({ item: expect.any(Object), item_id: "test-item", quantity: 1, }), ]), }) ) }) test("creates a replace claim fulfillment", async () => { await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const option = await simpleShippingOptionFactory(dbConnection, { region_id: "test-region", }) const api = useApi() const createRes = await api.post( `/admin/orders/${order.id}/claims`, { type: "replace", shipping_methods: [ { option_id: option.id, price: 0, }, ], additional_items: [{ variant_id: "test-variant", quantity: 1 }], claim_items: [ { item_id: "test-item", reason: "missing_item", quantity: 1, }, ], }, { headers: { "x-medusa-access-token": "test_token", }, } ) const response = await api.post( `/admin/orders/${order.id}/claims/${createRes.data.order.claims[0].id}/fulfillments`, {}, { headers: { "x-medusa-access-token": "test_token", }, } ) expect(response.status).toEqual(200) }) test(" should throw and not have dangling claim order upon a claim creation without reasons on claim items", async () => { const api = useApi() await adminSeeder(dbConnection) const order = await createReturnableOrder(dbConnection) const option = await simpleShippingOptionFactory(dbConnection, { region_id: "test-region", }) const err = await api .post( `/admin/orders/${order.id}/claims`, { type: "replace", shipping_methods: [ { option_id: option.id, price: 0, }, ], additional_items: [{ variant_id: "test-variant", quantity: 1 }], claim_items: [ { item_id: "test-item", quantity: 1, }, ], }, { headers: { "x-medusa-access-token": "test_token", }, } ) .catch((e) => e) const claimOrders = await dbConnection.manager.query( `SELECT * FROM claim_order WHERE order_id = '${order.id}'` ) expect(err).toBeDefined() expect(err.response.status).toBe(400) expect(claimOrders).toEqual([]) }) }) export const createReturnableOrder = async (dbConnection, options = {}) => { await simpleProductFactory( dbConnection, { id: "test-product", variants: [ { id: "test-variant" }, { id: "variant-2", prices: [{ currency: "usd", amount: 1000 }] }, ], }, 100 ) let discounts = [] if (options.discount) { discounts = [ { code: "TESTCODE", }, ] } const order = await simpleOrderFactory(dbConnection, { email: "test@testson.com", tax_rate: null, fulfillment_status: "fulfilled", payment_status: "captured", region: { id: "test-region", name: "Test region", tax_rate: 12.5, // Should be ignored due to item tax line }, discounts, line_items: [ { id: "test-item", variant_id: "test-variant", quantity: 2, fulfilled_quantity: 2, shipped_quantity: 2, unit_price: 1000, tax_lines: [ { name: "default", code: "default", rate: 20, }, ], }, ], }) await simplePaymentFactory(dbConnection, { provider_id: "test-pay", order: order.id, amount: 2400, captured: true, }) return order }