diff --git a/integration-tests/api/__tests__/admin/note.js b/integration-tests/api/__tests__/admin/note.js index 4923f5cbd7..c785b59f33 100644 --- a/integration-tests/api/__tests__/admin/note.js +++ b/integration-tests/api/__tests__/admin/note.js @@ -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", () => { diff --git a/integration-tests/api/__tests__/admin/swaps.js b/integration-tests/api/__tests__/admin/swaps.js index c75ea5fdd6..0e09861eb4 100644 --- a/integration-tests/api/__tests__/admin/swaps.js +++ b/integration-tests/api/__tests__/admin/swaps.js @@ -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) }) diff --git a/integration-tests/api/__tests__/returns/index.js b/integration-tests/api/__tests__/returns/index.js index 02432bc060..de02d11553 100644 --- a/integration-tests/api/__tests__/returns/index.js +++ b/integration-tests/api/__tests__/returns/index.js @@ -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, }, ] : [], diff --git a/integration-tests/api/__tests__/store/regions.js b/integration-tests/api/__tests__/store/regions.js new file mode 100644 index 0000000000..4365692dec --- /dev/null +++ b/integration-tests/api/__tests__/store/regions.js @@ -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) + }) + }) +}) diff --git a/packages/generated/client-types/src/lib/models/AdminNotificationsListRes.ts b/packages/generated/client-types/src/lib/models/AdminNotificationsListRes.ts index 4f045be97f..62f853ab3b 100644 --- a/packages/generated/client-types/src/lib/models/AdminNotificationsListRes.ts +++ b/packages/generated/client-types/src/lib/models/AdminNotificationsListRes.ts @@ -7,4 +7,16 @@ import type { Notification } from "./Notification" export interface AdminNotificationsListRes { notifications: Array> + /** + * 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 } diff --git a/packages/generated/client-types/src/lib/models/StoreRegionsListRes.ts b/packages/generated/client-types/src/lib/models/StoreRegionsListRes.ts index caec712e17..0a98b227b6 100644 --- a/packages/generated/client-types/src/lib/models/StoreRegionsListRes.ts +++ b/packages/generated/client-types/src/lib/models/StoreRegionsListRes.ts @@ -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 } diff --git a/packages/medusa/src/api/routes/admin/notes/list-notes.ts b/packages/medusa/src/api/routes/admin/notes/list-notes.ts index 29d16cbf11..0d6bb05b4f 100644 --- a/packages/medusa/src/api/routes/admin/notes/list-notes.ts +++ b/packages/medusa/src/api/routes/admin/notes/list-notes.ts @@ -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, }) diff --git a/packages/medusa/src/api/routes/admin/notifications/index.ts b/packages/medusa/src/api/routes/admin/notifications/index.ts index 36f4739944..cb81534cd4 100644 --- a/packages/medusa/src/api/routes/admin/notifications/index.ts +++ b/packages/medusa/src/api/routes/admin/notifications/index.ts @@ -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[] } diff --git a/packages/medusa/src/api/routes/admin/notifications/list-notifications.ts b/packages/medusa/src/api/routes/admin/notifications/list-notifications.ts index c38d804c78..5bad762e0a 100644 --- a/packages/medusa/src/api/routes/admin/notifications/list-notifications.ts +++ b/packages/medusa/src/api/routes/admin/notifications/list-notifications.ts @@ -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 - 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 { diff --git a/packages/medusa/src/api/routes/admin/returns/list-returns.ts b/packages/medusa/src/api/routes/admin/returns/list-returns.ts index 93dc4626a6..8e608344cb 100644 --- a/packages/medusa/src/api/routes/admin/returns/list-returns.ts +++ b/packages/medusa/src/api/routes/admin/returns/list-returns.ts @@ -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 - 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, }) diff --git a/packages/medusa/src/api/routes/admin/swaps/__tests__/list-swaps.js b/packages/medusa/src/api/routes/admin/swaps/__tests__/list-swaps.js index 200f800957..8a1a2381ae 100644 --- a/packages/medusa/src/api/routes/admin/swaps/__tests__/list-swaps.js +++ b/packages/medusa/src/api/routes/admin/swaps/__tests__/list-swaps.js @@ -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, diff --git a/packages/medusa/src/api/routes/admin/swaps/list-swaps.ts b/packages/medusa/src/api/routes/admin/swaps/list-swaps.ts index 82e0e48e3f..deb8d1faea 100644 --- a/packages/medusa/src/api/routes/admin/swaps/list-swaps.ts +++ b/packages/medusa/src/api/routes/admin/swaps/list-swaps.ts @@ -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 { diff --git a/packages/medusa/src/api/routes/store/regions/__tests__/list-regions.js b/packages/medusa/src/api/routes/store/regions/__tests__/list-regions.js index 935600f1d1..6d55a2a749 100644 --- a/packages/medusa/src/api/routes/store/regions/__tests__/list-regions.js +++ b/packages/medusa/src/api/routes/store/regions/__tests__/list-regions.js @@ -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: [ diff --git a/packages/medusa/src/api/routes/store/regions/index.ts b/packages/medusa/src/api/routes/store/regions/index.ts index 76413d9668..3b48dbac33 100644 --- a/packages/medusa/src/api/routes/store/regions/index.ts +++ b/packages/medusa/src/api/routes/store/regions/index.ts @@ -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[] } diff --git a/packages/medusa/src/api/routes/store/regions/list-regions.ts b/packages/medusa/src/api/routes/store/regions/list-regions.ts index 191f661be3..6c1f9ac514 100644 --- a/packages/medusa/src/api/routes/store/regions/list-regions.ts +++ b/packages/medusa/src/api/routes/store/regions/list-regions.ts @@ -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 { diff --git a/packages/medusa/src/services/__mocks__/swap.js b/packages/medusa/src/services/__mocks__/swap.js index c99bddd1ee..ec941ce632 100644 --- a/packages/medusa/src/services/__mocks__/swap.js +++ b/packages/medusa/src/services/__mocks__/swap.js @@ -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(() => { diff --git a/packages/medusa/src/services/__tests__/note.js b/packages/medusa/src/services/__tests__/note.js index 39cfe5eb96..887972eb4c 100644 --- a/packages/medusa/src/services/__tests__/note.js +++ b/packages/medusa/src/services/__tests__/note.js @@ -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"), }, diff --git a/packages/medusa/src/services/note.ts b/packages/medusa/src/services/note.ts index 910c013ef7..e305fd50d8 100644 --- a/packages/medusa/src/services/note.ts +++ b/packages/medusa/src/services/note.ts @@ -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 { + 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, + config: FindConfig = { + 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) } /** diff --git a/packages/medusa/src/services/notification.ts b/packages/medusa/src/services/notification.ts index 0587e1952d..c515f88c5b 100644 --- a/packages/medusa/src/services/notification.ts +++ b/packages/medusa/src/services/notification.ts @@ -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 { + 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, + config: FindConfig = { + 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) } /** diff --git a/packages/medusa/src/services/return.ts b/packages/medusa/src/services/return.ts index d9231288e6..a1edd55e03 100644 --- a/packages/medusa/src/services/return.ts +++ b/packages/medusa/src/services/return.ts @@ -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 { + 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, + config: FindConfig = { + 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) } /** diff --git a/packages/medusa/src/services/swap.ts b/packages/medusa/src/services/swap.ts index 6c01b21495..1c9ba5ab88 100644 --- a/packages/medusa/src/services/swap.ts +++ b/packages/medusa/src/services/swap.ts @@ -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 { + 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, + config: FindConfig = { + 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) } /**