Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(medusa,inventory,types): Expand list-reservation capabilities #3979

Merged
merged 26 commits into from
May 24, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8fbcd27
add fields
pKorsholm May 1, 2023
5f87ff2
add title in migration
pKorsholm May 1, 2023
b41d97c
update api endpoints to reflect datamodel changes
pKorsholm May 1, 2023
1d97038
update migration exports for inventory module
pKorsholm May 1, 2023
b611605
add changeset
pKorsholm May 1, 2023
6f37d1d
Merge branch 'develop' into feat/reservation-item-inventory-item-updates
pKorsholm May 1, 2023
341a457
initial changes to enable list-reservations
pKorsholm May 2, 2023
36193c9
add changeset
pKorsholm May 2, 2023
1b132ac
update oas
pKorsholm May 2, 2023
153be07
revert change
pKorsholm May 2, 2023
49dbddc
test for querying with multiple search params
pKorsholm May 2, 2023
fb5b330
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 11, 2023
39d0de6
cleanup changesets
pKorsholm May 11, 2023
053131d
undo import changes
pKorsholm May 11, 2023
cb390e9
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 15, 2023
5c2d39a
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 16, 2023
f51a044
snake_case
pKorsholm May 16, 2023
46da24b
Merge branch 'develop' into feat/expand-filter-reservations
olivermrbl May 16, 2023
fd1fdce
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 22, 2023
bb0354d
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 22, 2023
9f47fec
fix feedback
pKorsholm May 22, 2023
9bec4ba
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 23, 2023
66a9c73
Merge branch 'develop' into feat/expand-filter-reservations
pKorsholm May 23, 2023
2420401
remove searchOperator for string
pKorsholm May 23, 2023
2fe36f1
re-add starts_with and ends_with
pKorsholm May 24, 2023
950ac84
Merge branch 'develop' into feat/expand-filter-reservations
kodiakhq[bot] May 24, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/smooth-numbers-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@medusajs/client-types": patch
"@medusajs/inventory": patch
"@medusajs/medusa": patch
"@medusajs/types": patch
---

feat(client-types, inventory, medusa, types): add additional filtering capabilities to list-reservations
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,185 @@ describe("Inventory Items endpoints", () => {
})
})

describe("List reservation items", () => {
let item2
let location2
let reservation2

beforeEach(async () => {
const api = useApi()
const stockRes = await api.post(
`/admin/stock-locations`,
{
name: "Fake Warehouse 1",
},
adminHeaders
)

location2 = stockRes.data.stock_location.id

await salesChannelLocationService.associateLocation(
"test-channel",
location2
)

const inventoryItem1 = await inventoryService.createInventoryItem({
sku: "12345",
})
item2 = inventoryItem1.id

await inventoryService.createInventoryLevel({
inventory_item_id: item2,
location_id: location2,
stocked_quantity: 100,
})

order = await simpleOrderFactory(dbConnection, {
sales_channel: "test-channel",
line_items: [
{
variant_id: variantId,
quantity: 2,
id: "line-item-id-2",
},
],
shipping_methods: [
{
shipping_option: {
region_id: regionId,
},
},
],
})

const orderRes = await api.get(
`/admin/orders/${order.id}`,
adminHeaders
)

reservation2 = await inventoryService.createReservationItem({
line_item_id: "line-item-id-2",
inventory_item_id: item2,
location_id: location2,
description: "test description",
quantity: 1,
})
})

it("lists reservation items", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations`,
adminHeaders
)
expect(reservationsRes.data.reservations.length).toBe(2)
expect(reservationsRes.data.reservations).toEqual(
expect.arrayContaining([
expect.objectContaining({
id: reservationItem.id,
}),
expect.objectContaining({
id: reservation2.id,
}),
])
)
})

describe("Filters reservation items", () => {
it("filters by location", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations?location_id[]=${locationId}`,
adminHeaders
)
expect(reservationsRes.data.reservations.length).toBe(1)
expect(reservationsRes.data.reservations[0].location_id).toBe(
locationId
)
})

it("filters by itemID", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations?inventory_item_id[]=${item2}`,
adminHeaders
)
expect(reservationsRes.data.reservations.length).toBe(1)
expect(reservationsRes.data.reservations[0].inventory_item_id).toBe(
item2
)
})

it("filters by quantity", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations?quantity[gt]=1`,
adminHeaders
)

expect(reservationsRes.data.reservations.length).toBe(1)
expect(reservationsRes.data.reservations[0].id).toBe(
reservationItem.id
)
})

it("filters by date", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations?created_at[gte]=${new Date(
reservation2.created_at
).toISOString()}`,
adminHeaders
)

expect(reservationsRes.data.reservations.length).toBe(1)
expect(reservationsRes.data.reservations[0].id).toBe(reservation2.id)
})

it("filters by description using equals", async () => {
const api = useApi()

const reservationsRes = await api
.get(
`/admin/reservations?description=test%20description`,
adminHeaders
)
.catch(console.log)

expect(reservationsRes.data.reservations.length).toBe(1)
expect(reservationsRes.data.reservations[0].id).toBe(reservation2.id)
})

it("filters by description using equals removes results", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations?description=description`,
adminHeaders
)

expect(reservationsRes.data.reservations.length).toBe(0)
})

it("filters by description using contains", async () => {
const api = useApi()

const reservationsRes = await api.get(
`/admin/reservations?description[contains]=descri`,
adminHeaders
)

expect(reservationsRes.data.reservations.length).toBe(1)
expect(reservationsRes.data.reservations[0].id).toBe(reservation2.id)
})
})
})

it("lists reservations with inventory_items and line items", async () => {
const api = useApi()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,50 @@ export interface AdminGetReservationsParams {
*/
gte?: number
}
/**
* A param for search reservation descriptions
*/
description?:
| string
| {
/**
* filter by reservation description containing search string.
*/
contains?: string
/**
* filter by reservation description equals search string.
*/
equals?: string
/**
* filter by reservation description starting with search string.
*/
starts_with?: string
/**
* filter by reservation description ending with search string.
*/
ends_with?: string
}
/**
* Date comparison for when resulting reservations were created.
*/
created_at?: {
/**
* filter by dates less than this date
*/
lt?: string
/**
* filter by dates greater than this date
*/
gt?: string
/**
* filter by dates less than or equal to this date
*/
lte?: string
/**
* filter by dates greater than or equal to this date
*/
gte?: string
}
/**
* How many Reservations to skip in the result.
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/inventory/src/services/reservation-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export default class ReservationItemService {
const itemRepository = manager.getRepository(ReservationItem)

const query = buildQuery(selector, config) as FindManyOptions

return await itemRepository.find(query)
}

Expand All @@ -79,6 +80,7 @@ export default class ReservationItemService {
const itemRepository = manager.getRepository(ReservationItem)

const query = buildQuery(selector, config) as FindManyOptions

return await itemRepository.findAndCount(query)
}

Expand Down
6 changes: 3 additions & 3 deletions packages/inventory/src/utils/query.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { EntityManager, FindOptionsWhere, ILike } from "typeorm"
import {
ExtendedFindConfig,
FilterableInventoryItemProps,
FindConfig,
} from "@medusajs/types"
import { objectToStringPath, buildQuery } from "@medusajs/utils"
import { EntityManager, FindOptionsWhere, ILike } from "typeorm"
import { InventoryItem } from "../models"
import { InventoryItem, ReservationItem } from "../models"
import { buildQuery, objectToStringPath } from "@medusajs/utils"

export function getListQuery(
manager: EntityManager,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { IsArray, IsOptional, IsString, ValidateNested } from "class-validator"
import {
DateComparisonOperator,
NumericalComparisonOperator,
StringComparisonOperator,
extendedFindParamsMixin,
} from "../../../../types/common"
import { IsArray, IsOptional, IsString, ValidateNested } from "class-validator"
import { Request, Response } from "express"

import { EntityManager } from "typeorm"
Expand Down Expand Up @@ -65,6 +67,48 @@ import { joinLineItems } from "./utils/join-line-items"
* gte:
* type: number
* description: filter by reservation quantity greater than or equal to this number
* - in: query
* name: description
* description: A param for search reservation descriptions
* schema:
* oneOf:
* - type: string
* - type: object
* properties:
* contains:
* type: string
* description: filter by reservation description containing search string.
* equals:
* type: string
* description: filter by reservation description equals search string.
* starts_with:
* type: string
* description: filter by reservation description starting with search string.
* ends_with:
* type: string
* description: filter by reservation description ending with search string.
* - in: query
* name: created_at
* description: Date comparison for when resulting reservations were created.
* schema:
* type: object
* properties:
* lt:
* type: string
* description: filter by dates less than this date
* format: date
* gt:
* type: string
* description: filter by dates greater than this date
* format: date
* lte:
* type: string
* description: filter by dates less than or equal to this date
* format: date
* gte:
* type: string
* description: filter by dates greater than or equal to this date
* format: date
* - (query) offset=0 {integer} How many Reservations to skip in the result.
* - (query) limit=20 {integer} Limit the number of Reservations returned.
* - (query) expand {string} (Comma separated) Which fields should be expanded in the product category.
Expand Down Expand Up @@ -184,4 +228,13 @@ export class AdminGetReservationsParams extends extendedFindParamsMixin({
@ValidateNested()
@Type(() => NumericalComparisonOperator)
quantity?: NumericalComparisonOperator

@IsOptional()
@ValidateNested()
@Type(() => DateComparisonOperator)
created_at?: DateComparisonOperator

@IsOptional()
@IsType([StringComparisonOperator, String])
description?: string | StringComparisonOperator
}
Loading