feat(medusa): Add proper pagination (#4517)
* update method for listing regions * add changeset * fix unit tests * listAndCount swaps * add count calculation to list-returns * swap integration test * notes pagination * pagination props for notifications * listAndCount store regions * fix nit * fix note unit test * update list-regions store unit test * cleanup integration test * rename introduced tests --------- Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
@@ -163,6 +163,22 @@ describe("/admin/notes", () => {
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
it("should list the notes with correct count in pagination", async () => {
|
||||
const api = useApi()
|
||||
const response = await api
|
||||
.get("/admin/notes?limit=2", {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
expect(response.data.notes.length).toEqual(2)
|
||||
expect(response.data.count).toEqual(3)
|
||||
})
|
||||
})
|
||||
|
||||
describe("POST /admin/notes/:id", () => {
|
||||
|
||||
@@ -24,6 +24,12 @@ const {
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
|
||||
describe("/admin/swaps", () => {
|
||||
describe("tax exclusive", () => {
|
||||
let medusaProcess
|
||||
@@ -57,11 +63,7 @@ describe("/admin/swaps", () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/swaps/test-swap", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.get("/admin/swaps/test-swap", adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
@@ -88,11 +90,7 @@ describe("/admin/swaps", () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/swaps/disc-swap", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.get("/admin/swaps/disc-swap", adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
@@ -131,11 +129,7 @@ describe("/admin/swaps", () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api
|
||||
.get("/admin/swaps/", {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.get("/admin/swaps/", adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
@@ -150,6 +144,17 @@ describe("/admin/swaps", () => {
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should list the swaps with correct pagination", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.get("/admin/swaps?limit=5", adminHeaders)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
expect(response.data.count).toBe(8)
|
||||
expect(response.data.limit).toBe(5)
|
||||
expect(response.data.swaps.length).toBe(5)
|
||||
})
|
||||
})
|
||||
|
||||
describe("Complete swap flow", () => {
|
||||
@@ -268,11 +273,7 @@ describe("/admin/swaps", () => {
|
||||
{
|
||||
items: [{ item_id: "line-item", quantity: 1 }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const fulfillmentId = fulfilledOrder.data.order.fulfillments[0].id
|
||||
@@ -282,22 +283,10 @@ describe("/admin/swaps", () => {
|
||||
{
|
||||
fulfillment_id: fulfillmentId,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
await api.post(
|
||||
`/admin/orders/${orderId}/capture`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
await api.post(`/admin/orders/${orderId}/capture`, {}, adminHeaders)
|
||||
|
||||
// ********* CREATE SWAP *********
|
||||
const createSwap = await api.post(
|
||||
@@ -311,11 +300,7 @@ describe("/admin/swaps", () => {
|
||||
],
|
||||
additional_items: [{ variant_id: "prod-b-var", quantity: 1 }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let swap = createSwap.data.order.swaps[0]
|
||||
@@ -335,11 +320,7 @@ describe("/admin/swaps", () => {
|
||||
await api.post(`/store/carts/${swap.cart_id}/complete`)
|
||||
|
||||
swap = await api
|
||||
.get(`/admin/swaps/${swap.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.get(`/admin/swaps/${swap.id}`, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
@@ -495,11 +476,7 @@ describe("/admin/swaps", () => {
|
||||
{
|
||||
items: [{ item_id: "line-item", quantity: 1 }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const fulfillmentId = fulfilledOrder.data.order.fulfillments[0].id
|
||||
@@ -509,22 +486,10 @@ describe("/admin/swaps", () => {
|
||||
{
|
||||
fulfillment_id: fulfillmentId,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
await api.post(
|
||||
`/admin/orders/${orderId}/capture`,
|
||||
{},
|
||||
{
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
)
|
||||
await api.post(`/admin/orders/${orderId}/capture`, {}, adminHeaders)
|
||||
|
||||
// ********* CREATE SWAP *********
|
||||
const createSwap = await api.post(
|
||||
@@ -538,11 +503,7 @@ describe("/admin/swaps", () => {
|
||||
],
|
||||
additional_items: [{ variant_id: "prod-b-var", quantity: 1 }],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
let swap = createSwap.data.order.swaps[0]
|
||||
@@ -562,11 +523,7 @@ describe("/admin/swaps", () => {
|
||||
await api.post(`/store/carts/${swap.cart_id}/complete`)
|
||||
|
||||
swap = await api
|
||||
.get(`/admin/swaps/${swap.id}`, {
|
||||
headers: {
|
||||
Authorization: "Bearer test_token",
|
||||
},
|
||||
})
|
||||
.get(`/admin/swaps/${swap.id}`, adminHeaders)
|
||||
.catch((err) => {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
@@ -18,6 +18,12 @@ const {
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
const adminHeaders = {
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
|
||||
describe("/admin/orders", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
@@ -60,11 +66,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
@@ -103,11 +105,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
@@ -156,11 +154,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
@@ -215,11 +209,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
@@ -364,11 +354,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
@@ -421,7 +407,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{ headers: { authorization: "Bearer test_token" } }
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const claimId = createRes.data.order.claims[0].id
|
||||
@@ -430,7 +416,7 @@ describe("/admin/orders", () => {
|
||||
const claimFulfillmentCreatedResponse = await api.post(
|
||||
`/admin/orders/${order.id}/claims/${claimId}/fulfillments`,
|
||||
{},
|
||||
{ headers: { authorization: "Bearer test_token" } }
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const fulfillmentId =
|
||||
@@ -438,7 +424,7 @@ describe("/admin/orders", () => {
|
||||
await api.post(
|
||||
`/admin/orders/${order.id}/claims/${claimId}/shipments`,
|
||||
{ fulfillment_id: fulfillmentId },
|
||||
{ headers: { authorization: "Bearer test_token" } }
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const returnCreatedResponse = await api.post(
|
||||
@@ -452,11 +438,7 @@ describe("/admin/orders", () => {
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
const returnOrder = returnCreatedResponse.data.order.returns[0]
|
||||
@@ -469,23 +451,56 @@ describe("/admin/orders", () => {
|
||||
quantity: i.quantity,
|
||||
})),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
authorization: "Bearer test_token",
|
||||
},
|
||||
}
|
||||
adminHeaders
|
||||
)
|
||||
|
||||
expect(returnReceivedResponse.status).toEqual(200)
|
||||
})
|
||||
|
||||
it("shoutl list the returns with correct pagination", async () => {
|
||||
await adminSeeder(dbConnection)
|
||||
const api = useApi()
|
||||
|
||||
const createOrderAndReturn = async (suffix = "") => {
|
||||
const order = await createReturnableOrder(
|
||||
dbConnection,
|
||||
{
|
||||
discount: false,
|
||||
oldTaxes: false,
|
||||
},
|
||||
suffix
|
||||
)
|
||||
|
||||
const response = await api.post(
|
||||
`/admin/orders/${order.id}/return`,
|
||||
{
|
||||
items: [
|
||||
{
|
||||
item_id: "test-item" + suffix,
|
||||
quantity: 1,
|
||||
note: "TOO SMALL",
|
||||
},
|
||||
],
|
||||
},
|
||||
adminHeaders
|
||||
)
|
||||
}
|
||||
|
||||
await Promise.all([createOrderAndReturn(), createOrderAndReturn("-1")])
|
||||
|
||||
const result = await api.get(`/admin/returns?limit=1`, adminHeaders)
|
||||
|
||||
expect(result.status).toEqual(200)
|
||||
expect(result.data.count).toEqual(2)
|
||||
})
|
||||
})
|
||||
|
||||
const createReturnableOrder = async (dbConnection, options) => {
|
||||
const createReturnableOrder = async (dbConnection, options, suffix = "") => {
|
||||
await simpleProductFactory(
|
||||
dbConnection,
|
||||
{
|
||||
id: "test-product",
|
||||
variants: [{ id: "test-variant" }],
|
||||
id: "test-product" + suffix,
|
||||
variants: [{ id: "test-variant" + suffix }],
|
||||
},
|
||||
100
|
||||
)
|
||||
@@ -495,24 +510,24 @@ const createReturnableOrder = async (dbConnection, options) => {
|
||||
if (options.discount) {
|
||||
discounts = [
|
||||
{
|
||||
code: "TESTCODE",
|
||||
code: "TESTCODE" + suffix,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
return await simpleOrderFactory(dbConnection, {
|
||||
email: "test@testson.com",
|
||||
email: "test@testson.com" + suffix,
|
||||
tax_rate: options.oldTaxes ? undefined : null,
|
||||
region: {
|
||||
id: "test-region",
|
||||
id: "test-region" + suffix,
|
||||
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",
|
||||
id: "test-item" + suffix,
|
||||
variant_id: "test-variant" + suffix,
|
||||
quantity: 2,
|
||||
fulfilled_quantity: options.shipped ? 2 : undefined,
|
||||
shipped_quantity: options.shipped ? 2 : undefined,
|
||||
@@ -521,9 +536,9 @@ const createReturnableOrder = async (dbConnection, options) => {
|
||||
? [
|
||||
{
|
||||
amount: 200,
|
||||
discount_code: "TESTCODE",
|
||||
discount_code: "TESTCODE" + suffix,
|
||||
description: "discount",
|
||||
item_id: "test-item",
|
||||
item_id: "test-item" + suffix,
|
||||
},
|
||||
]
|
||||
: [],
|
||||
|
||||
75
integration-tests/api/__tests__/store/regions.js
Normal file
75
integration-tests/api/__tests__/store/regions.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const path = require("path")
|
||||
const {
|
||||
Region,
|
||||
ReturnReason,
|
||||
Order,
|
||||
Customer,
|
||||
ShippingProfile,
|
||||
Product,
|
||||
ProductVariant,
|
||||
ShippingOption,
|
||||
FulfillmentProvider,
|
||||
LineItem,
|
||||
Discount,
|
||||
DiscountRule,
|
||||
} = require("@medusajs/medusa")
|
||||
|
||||
const setupServer = require("../../../helpers/setup-server")
|
||||
const { useApi } = require("../../../helpers/use-api")
|
||||
const { initDb, useDb } = require("../../../helpers/use-db")
|
||||
|
||||
jest.setTimeout(30000)
|
||||
|
||||
describe("/store/carts", () => {
|
||||
let medusaProcess
|
||||
let dbConnection
|
||||
|
||||
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()
|
||||
})
|
||||
|
||||
describe("GET /store/regions", () => {
|
||||
beforeEach(async () => {
|
||||
const manager = dbConnection.manager
|
||||
|
||||
await manager.insert(Region, {
|
||||
id: "region",
|
||||
name: "Test Region",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
await manager.insert(Region, {
|
||||
id: "region-1",
|
||||
name: "Test Region 1",
|
||||
currency_code: "usd",
|
||||
tax_rate: 0,
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
const db = useDb()
|
||||
await db.teardown()
|
||||
})
|
||||
|
||||
it("should list the store regions with pagination", async () => {
|
||||
const api = useApi()
|
||||
|
||||
const response = await api.get("/store/regions?limit=1&offset=1")
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
|
||||
expect(response.data.regions.length).toEqual(1)
|
||||
expect(response.data.count).toEqual(2)
|
||||
expect(response.data.offset).toEqual(1)
|
||||
expect(response.data.limit).toEqual(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -7,4 +7,16 @@ import type { Notification } from "./Notification"
|
||||
|
||||
export interface AdminNotificationsListRes {
|
||||
notifications: Array<SetRelation<Notification, "resends">>
|
||||
/**
|
||||
* The total number of notifications
|
||||
*/
|
||||
count?: number
|
||||
/**
|
||||
* The number of notifications skipped before these notifications
|
||||
*/
|
||||
offset?: number
|
||||
/**
|
||||
* The number of notifications per page
|
||||
*/
|
||||
limit?: number
|
||||
}
|
||||
|
||||
@@ -12,4 +12,16 @@ export interface StoreRegionsListRes {
|
||||
"countries" | "payment_providers" | "fulfillment_providers"
|
||||
>
|
||||
>
|
||||
/**
|
||||
* The total number of items available
|
||||
*/
|
||||
count?: number
|
||||
/**
|
||||
* The number of items skipped before these items
|
||||
*/
|
||||
offset?: number
|
||||
/**
|
||||
* The number of items per page
|
||||
*/
|
||||
limit?: number
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ export default async (req, res) => {
|
||||
}
|
||||
|
||||
const noteService: NoteService = req.scope.resolve("noteService")
|
||||
const notes = await noteService.list(selector, {
|
||||
const [notes, count] = await noteService.listAndCount(selector, {
|
||||
take: validated.limit,
|
||||
skip: validated.offset,
|
||||
relations: ["author"],
|
||||
@@ -77,7 +77,7 @@ export default async (req, res) => {
|
||||
|
||||
res.status(200).json({
|
||||
notes,
|
||||
count: notes.length,
|
||||
count,
|
||||
offset: validated.offset,
|
||||
limit: validated.limit,
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Router } from "express"
|
||||
import { Notification } from "./../../../../"
|
||||
import { PaginatedResponse } from "@medusajs/types"
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
|
||||
const route = Router()
|
||||
@@ -50,8 +51,17 @@ export const defaultAdminNotificationsFields = [
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: "#/components/schemas/Notification"
|
||||
* count:
|
||||
* type: integer
|
||||
* description: The total number of notifications
|
||||
* offset:
|
||||
* type: integer
|
||||
* description: The number of notifications skipped before these notifications
|
||||
* limit:
|
||||
* type: integer
|
||||
* description: The number of notifications per page
|
||||
*/
|
||||
export type AdminNotificationsListRes = {
|
||||
export type AdminNotificationsListRes = PaginatedResponse & {
|
||||
notifications: Notification[]
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ import {
|
||||
defaultAdminNotificationsFields,
|
||||
defaultAdminNotificationsRelations,
|
||||
} from "./"
|
||||
import { Notification } from "../../../../models"
|
||||
import { FindConfig } from "../../../../types/common"
|
||||
|
||||
import { FindConfig } from "../../../../types/common"
|
||||
import { Notification } from "../../../../models"
|
||||
import { NotificationService } from "../../../../services"
|
||||
import { Type } from "class-transformer"
|
||||
import { pick } from "lodash"
|
||||
@@ -135,7 +135,10 @@ export default async (req, res) => {
|
||||
order: { created_at: "DESC" },
|
||||
} as FindConfig<Notification>
|
||||
|
||||
const notifications = await notificationService.list(selector, listConfig)
|
||||
const [notifications, count] = await notificationService.listAndCount(
|
||||
selector,
|
||||
listConfig
|
||||
)
|
||||
|
||||
const resultFields = [
|
||||
...(listConfig.select ?? []),
|
||||
@@ -143,7 +146,7 @@ export default async (req, res) => {
|
||||
]
|
||||
const data = notifications.map((o) => pick(o, resultFields))
|
||||
|
||||
res.json({ notifications: data })
|
||||
res.json({ notifications: data, count, limit, offset })
|
||||
}
|
||||
|
||||
export class AdminGetNotificationsParams {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { IsNumber, IsOptional } from "class-validator"
|
||||
|
||||
import { ReturnService } from "../../../../services"
|
||||
import { Type } from "class-transformer"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
import { FindConfig } from "../../../../types/common"
|
||||
import { Return } from "../../../../models"
|
||||
import { ReturnService } from "../../../../services"
|
||||
import { Type } from "class-transformer"
|
||||
import { defaultRelationsList } from "."
|
||||
import { validator } from "../../../../utils/validator"
|
||||
|
||||
/**
|
||||
* @oas [get] /admin/returns
|
||||
@@ -73,11 +73,13 @@ export default async (req, res) => {
|
||||
order: { created_at: "DESC" },
|
||||
} as FindConfig<Return>
|
||||
|
||||
const returns = await returnService.list(selector, { ...listConfig })
|
||||
const [returns, count] = await returnService.listAndCount(selector, {
|
||||
...listConfig,
|
||||
})
|
||||
|
||||
res.json({
|
||||
returns,
|
||||
count: returns.length,
|
||||
count,
|
||||
offset: validated.offset,
|
||||
limit: validated.limit,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { SwapServiceMock } from "../../../../../services/__mocks__/swap"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
|
||||
const defaultListOptions = {
|
||||
take: 50,
|
||||
@@ -27,8 +27,8 @@ describe("GET /admin/swaps/", () => {
|
||||
})
|
||||
|
||||
it("calls swapService list with default pagination and sorting options", () => {
|
||||
expect(SwapServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
expect(SwapServiceMock.list).toHaveBeenCalledWith(
|
||||
expect(SwapServiceMock.listAndCount).toHaveBeenCalledTimes(1)
|
||||
expect(SwapServiceMock.listAndCount).toHaveBeenCalledWith(
|
||||
{},
|
||||
{
|
||||
...defaultListOptions,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Type } from "class-transformer"
|
||||
import { IsInt, IsOptional } from "class-validator"
|
||||
|
||||
import { SwapService } from "../../../../services"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
import { FindConfig } from "../../../../types/common"
|
||||
import { Swap } from "../../../../models"
|
||||
import { SwapService } from "../../../../services"
|
||||
import { Type } from "class-transformer"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
|
||||
/**
|
||||
* @oas [get] /admin/swaps
|
||||
@@ -72,9 +72,11 @@ export default async (req, res) => {
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
|
||||
const swaps = await swapService.list(selector, { ...listConfig })
|
||||
const [swaps, count] = await swapService.listAndCount(selector, {
|
||||
...listConfig,
|
||||
})
|
||||
|
||||
res.json({ swaps, count: swaps.length, offset, limit })
|
||||
res.json({ swaps, count, offset, limit })
|
||||
}
|
||||
|
||||
export class AdminGetSwapsParams {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
import { RegionServiceMock } from "../../../../../services/__mocks__/region"
|
||||
import { request } from "../../../../../helpers/test-request"
|
||||
|
||||
describe("List regions", () => {
|
||||
describe("list regions", () => {
|
||||
@@ -14,8 +14,8 @@ describe("List regions", () => {
|
||||
})
|
||||
|
||||
it("calls list from region service", () => {
|
||||
expect(RegionServiceMock.list).toHaveBeenCalledTimes(1)
|
||||
expect(RegionServiceMock.list).toHaveBeenCalledWith(
|
||||
expect(RegionServiceMock.listAndCount).toHaveBeenCalledTimes(1)
|
||||
expect(RegionServiceMock.listAndCount).toHaveBeenCalledWith(
|
||||
{},
|
||||
{
|
||||
relations: [
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { PaginatedResponse } from "@medusajs/types"
|
||||
import { Region } from "./../../../../"
|
||||
import { Router } from "express"
|
||||
import middlewares from "../../../middlewares"
|
||||
import { Region } from "./../../../../"
|
||||
|
||||
const route = Router()
|
||||
|
||||
@@ -38,8 +39,17 @@ export const defaultRelations = [
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: "#/components/schemas/Region"
|
||||
* count:
|
||||
* type: integer
|
||||
* description: The total number of items available
|
||||
* offset:
|
||||
* type: integer
|
||||
* description: The number of items skipped before these items
|
||||
* limit:
|
||||
* type: integer
|
||||
* description: The number of items per page
|
||||
*/
|
||||
export type StoreRegionsListRes = {
|
||||
export type StoreRegionsListRes = PaginatedResponse & {
|
||||
regions: Region[]
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ import { IsInt, IsOptional, ValidateNested } from "class-validator"
|
||||
import { DateComparisonOperator } from "../../../../types/common"
|
||||
import RegionService from "../../../../services/region"
|
||||
import { Type } from "class-transformer"
|
||||
import { defaultRelations } from "."
|
||||
import { omit } from "lodash"
|
||||
import { validator } from "../../../../utils/validator"
|
||||
import { defaultRelations } from "."
|
||||
|
||||
/**
|
||||
* @oas [get] /store/regions
|
||||
@@ -110,9 +110,12 @@ export default async (req, res) => {
|
||||
take: limit,
|
||||
}
|
||||
|
||||
const regions = await regionService.list(filterableFields, listConfig)
|
||||
const [regions, count] = await regionService.listAndCount(
|
||||
filterableFields,
|
||||
listConfig
|
||||
)
|
||||
|
||||
res.json({ regions })
|
||||
res.json({ regions, count, limit, offset })
|
||||
}
|
||||
|
||||
export class StoreGetRegionsParams {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
|
||||
export const SwapServiceMock = {
|
||||
withTransaction: function() {
|
||||
withTransaction: function () {
|
||||
return this
|
||||
},
|
||||
registerCartCompletion: jest.fn().mockImplementation(data => {
|
||||
registerCartCompletion: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve({ id: "test-swap" })
|
||||
}),
|
||||
create: jest.fn().mockImplementation(data => {
|
||||
create: jest.fn().mockImplementation((data) => {
|
||||
return Promise.resolve()
|
||||
}),
|
||||
retrieve: jest.fn().mockImplementation(data => {
|
||||
retrieve: jest.fn().mockImplementation((data) => {
|
||||
switch (data) {
|
||||
case IdMap.getId("test-swap"):
|
||||
return Promise.resolve({
|
||||
@@ -21,11 +21,11 @@ export const SwapServiceMock = {
|
||||
return Promise.resolve({ id: "test-swap" })
|
||||
}
|
||||
}),
|
||||
cancel: jest.fn().mockImplementation(f => {
|
||||
cancel: jest.fn().mockImplementation((f) => {
|
||||
return Promise.resolve({ f })
|
||||
}),
|
||||
|
||||
cancelFulfillment: jest.fn().mockImplementation(f => {
|
||||
cancelFulfillment: jest.fn().mockImplementation((f) => {
|
||||
return Promise.resolve({ id: IdMap.getId("test-swap") })
|
||||
}),
|
||||
list: jest.fn().mockImplementation((...args) => {
|
||||
@@ -34,6 +34,12 @@ export const SwapServiceMock = {
|
||||
{ id: IdMap.getId("test-swap-1") },
|
||||
])
|
||||
}),
|
||||
listAndCount: jest.fn().mockImplementation((...args) => {
|
||||
return Promise.resolve([
|
||||
[{ id: IdMap.getId("test-swap") }, { id: IdMap.getId("test-swap-1") }],
|
||||
2,
|
||||
])
|
||||
}),
|
||||
}
|
||||
|
||||
const mock = jest.fn().mockImplementation(() => {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import NoteService from "../note"
|
||||
import { IdMap, MockManager, MockRepository } from "medusa-test-utils"
|
||||
|
||||
import { EventBusServiceMock } from "../__mocks__/event-bus"
|
||||
import NoteService from "../note"
|
||||
|
||||
describe("NoteService", () => {
|
||||
describe("list", () => {
|
||||
@@ -10,6 +11,12 @@ describe("NoteService", () => {
|
||||
{ id: IdMap.getId("note"), value: "some note" },
|
||||
])
|
||||
},
|
||||
findAndCount: (q) => {
|
||||
return Promise.resolve([
|
||||
[{ id: IdMap.getId("note"), value: "some note" }],
|
||||
1,
|
||||
])
|
||||
},
|
||||
})
|
||||
|
||||
const noteService = new NoteService({
|
||||
@@ -28,8 +35,8 @@ describe("NoteService", () => {
|
||||
relations: ["author"],
|
||||
}
|
||||
)
|
||||
expect(noteRepo.find).toHaveBeenCalledTimes(1)
|
||||
expect(noteRepo.find).toHaveBeenCalledWith({
|
||||
expect(noteRepo.findAndCount).toHaveBeenCalledTimes(1)
|
||||
expect(noteRepo.findAndCount).toHaveBeenCalledWith({
|
||||
where: {
|
||||
resource_id: IdMap.getId("note"),
|
||||
},
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
import { MedusaError, isDefined } from "medusa-core-utils"
|
||||
|
||||
import { CreateNoteInput } from "../types/note"
|
||||
import { EntityManager } from "typeorm"
|
||||
import { TransactionBaseService } from "../interfaces"
|
||||
import EventBusService from "./event-bus"
|
||||
import { Note } from "../models"
|
||||
import { NoteRepository } from "../repositories/note"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
import { CreateNoteInput } from "../types/note"
|
||||
import { TransactionBaseService } from "../interfaces"
|
||||
import { buildQuery } from "../utils"
|
||||
import EventBusService from "./event-bus"
|
||||
|
||||
type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
@@ -81,11 +82,32 @@ class NoteService extends TransactionBaseService {
|
||||
relations: [],
|
||||
}
|
||||
): Promise<Note[]> {
|
||||
const [result] = await this.listAndCount(selector, config)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/** Fetches all notes related to the given selector
|
||||
* @param selector - the query object for find
|
||||
* @param config - the configuration used to find the objects. contains relations, skip, and take.
|
||||
* @param config.relations - Which relations to include in the resulting list of Notes.
|
||||
* @param config.take - How many Notes to take in the resulting list of Notes.
|
||||
* @param config.skip - How many Notes to skip in the resulting list of Notes.
|
||||
* @return notes related to the given search.
|
||||
*/
|
||||
async listAndCount(
|
||||
selector: Selector<Note>,
|
||||
config: FindConfig<Note> = {
|
||||
skip: 0,
|
||||
take: 50,
|
||||
relations: [],
|
||||
}
|
||||
): Promise<[Note[], number]> {
|
||||
const noteRepo = this.activeManager_.withRepository(this.noteRepository_)
|
||||
|
||||
const query = buildQuery(selector, config)
|
||||
|
||||
return noteRepo.find(query)
|
||||
return noteRepo.findAndCount(query)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
AbstractNotificationService,
|
||||
TransactionBaseService,
|
||||
} from "../interfaces"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
|
||||
import { EntityManager } from "typeorm"
|
||||
import { Logger } from "../types/global"
|
||||
import { NotificationRepository } from "../repositories/notification"
|
||||
import { NotificationProviderRepository } from "../repositories/notification-provider"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
import { buildQuery } from "../utils"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
import { Notification } from "../models"
|
||||
import { NotificationProviderRepository } from "../repositories/notification-provider"
|
||||
import { NotificationRepository } from "../repositories/notification"
|
||||
import { buildQuery } from "../utils"
|
||||
|
||||
type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
@@ -82,11 +83,30 @@ class NotificationService extends TransactionBaseService {
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<Notification[]> {
|
||||
const [notifications] = await this.listAndCount(selector, config)
|
||||
|
||||
return notifications
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of notifications and total count.
|
||||
* @param selector - the params to select the notifications by.
|
||||
* @param config - the configuration to apply to the query
|
||||
* @return the notifications that satisfy the query as well as the count.
|
||||
*/
|
||||
async listAndCount(
|
||||
selector: Selector<Notification>,
|
||||
config: FindConfig<Notification> = {
|
||||
skip: 0,
|
||||
take: 50,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<[Notification[], number]> {
|
||||
const notiRepo = this.activeManager_.withRepository(
|
||||
this.notificationRepository_
|
||||
)
|
||||
const query = buildQuery(selector, config)
|
||||
return await notiRepo.find(query)
|
||||
return await notiRepo.findAndCount(query)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,22 +1,6 @@
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { DeepPartial, EntityManager } from "typeorm"
|
||||
import { TransactionBaseService } from "../interfaces"
|
||||
import {
|
||||
FulfillmentStatus,
|
||||
LineItem,
|
||||
Order,
|
||||
PaymentStatus,
|
||||
Return,
|
||||
ReturnItem,
|
||||
ReturnStatus,
|
||||
} from "../models"
|
||||
import { ReturnRepository } from "../repositories/return"
|
||||
import { ReturnItemRepository } from "../repositories/return-item"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
import { OrdersReturnItem } from "../types/orders"
|
||||
import { CreateReturnInput, UpdateReturnInput } from "../types/return"
|
||||
import { buildQuery, setMetadata } from "../utils"
|
||||
|
||||
import { DeepPartial, EntityManager } from "typeorm"
|
||||
import { FindConfig, Selector } from "../types/common"
|
||||
import {
|
||||
FulfillmentProviderService,
|
||||
LineItemService,
|
||||
@@ -27,6 +11,22 @@ import {
|
||||
TaxProviderService,
|
||||
TotalsService,
|
||||
} from "."
|
||||
import {
|
||||
FulfillmentStatus,
|
||||
LineItem,
|
||||
Order,
|
||||
PaymentStatus,
|
||||
Return,
|
||||
ReturnItem,
|
||||
ReturnStatus,
|
||||
} from "../models"
|
||||
import { MedusaError, isDefined } from "medusa-core-utils"
|
||||
import { buildQuery, setMetadata } from "../utils"
|
||||
|
||||
import { OrdersReturnItem } from "../types/orders"
|
||||
import { ReturnItemRepository } from "../repositories/return-item"
|
||||
import { ReturnRepository } from "../repositories/return"
|
||||
import { TransactionBaseService } from "../interfaces"
|
||||
|
||||
type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
@@ -146,11 +146,28 @@ class ReturnService extends TransactionBaseService {
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<Return[]> {
|
||||
const [returns] = await this.listAndCount(selector, config)
|
||||
return returns
|
||||
}
|
||||
|
||||
/**
|
||||
* @param selector - the query object for find
|
||||
* @param config - the config object for find
|
||||
* @return the result of the find operation
|
||||
*/
|
||||
async listAndCount(
|
||||
selector: Selector<Return>,
|
||||
config: FindConfig<Return> = {
|
||||
skip: 0,
|
||||
take: 50,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<[Return[], number]> {
|
||||
const returnRepo = this.activeManager_.withRepository(
|
||||
this.returnRepository_
|
||||
)
|
||||
const query = buildQuery(selector, config)
|
||||
return returnRepo.find(query)
|
||||
return returnRepo.findAndCount(query)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ import {
|
||||
} from "./index"
|
||||
import { EntityManager, In } from "typeorm"
|
||||
import { FindConfig, Selector, WithRequiredProperty } from "../types/common"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { MedusaError, isDefined } from "medusa-core-utils"
|
||||
import { buildQuery, setMetadata, validateId } from "../utils"
|
||||
|
||||
import { CreateShipmentConfig } from "../types/fulfillment"
|
||||
@@ -278,11 +278,31 @@ class SwapService extends TransactionBaseService {
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<Swap[]> {
|
||||
const [swaps] = await this.listAndCount(selector, config)
|
||||
|
||||
return swaps
|
||||
}
|
||||
|
||||
/**
|
||||
* List swaps.
|
||||
*
|
||||
* @param selector - the query object for find
|
||||
* @param config - the configuration used to find the objects. contains relations, skip, and take.
|
||||
* @return the result of the find operation
|
||||
*/
|
||||
async listAndCount(
|
||||
selector: Selector<Swap>,
|
||||
config: FindConfig<Swap> = {
|
||||
skip: 0,
|
||||
take: 50,
|
||||
order: { created_at: "DESC" },
|
||||
}
|
||||
): Promise<[Swap[], number]> {
|
||||
const swapRepo = this.activeManager_.withRepository(this.swapRepository_)
|
||||
const query = buildQuery(selector, config)
|
||||
query.relationLoadStrategy = "query"
|
||||
|
||||
return await swapRepo.find(query)
|
||||
return await swapRepo.findAndCount(query)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user