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: Add HTTP endpoints and workflows for price preference management #7960

Merged
merged 1 commit into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import { medusaIntegrationTestRunner } from "medusa-test-utils"
import {
createAdminUser,
adminHeaders,
} from "../../../../helpers/create-admin-user"

jest.setTimeout(30000)

medusaIntegrationTestRunner({
env: {},
testSuite: ({ dbConnection, getContainer, api }) => {
let pricePreference1
let pricePreference2

beforeEach(async () => {
const container = getContainer()
await createAdminUser(dbConnection, adminHeaders, container)

pricePreference1 = (
await api.post(
"/admin/price-preferences",
{
attribute: "region_id",
value: "region-1",
is_tax_inclusive: true,
},
adminHeaders
)
).data.price_preference

pricePreference2 = (
await api.post(
"/admin/price-preferences",
{
attribute: "currency_code",
value: "EUR",
is_tax_inclusive: true,
},
adminHeaders
)
).data.price_preference
})

describe("/admin/price-preferences", () => {
describe("POST /admin/price-preferences", () => {
it("creates a price preference", async () => {
const newPricePreference = (
await api.post(
"/admin/price-preferences",
{
attribute: "region_id",
value: "region-2",
is_tax_inclusive: true,
},
adminHeaders
)
).data.price_preference

expect(newPricePreference).toEqual(
expect.objectContaining({
attribute: "region_id",
value: "region-2",
is_tax_inclusive: true,
})
)
})

it("creates a price preference with false tax inclusivity by default", async () => {
const newPricePreference = (
await api.post(
"/admin/price-preferences",
{
attribute: "region_id",
value: "region-2",
},
adminHeaders
)
).data.price_preference

expect(newPricePreference).toEqual(
expect.objectContaining({
attribute: "region_id",
value: "region-2",
is_tax_inclusive: false,
})
)
})
})

describe("GET /admin/price-preferences", () => {
it("returns a list of price preferences", async () => {
const response = (
await api.get("/admin/price-preferences", adminHeaders)
).data.price_preferences

expect(response).toEqual(
expect.arrayContaining([
expect.objectContaining({
attribute: "region_id",
value: "region-1",
is_tax_inclusive: true,
}),
expect.objectContaining({
attribute: "currency_code",
value: "EUR",
is_tax_inclusive: true,
}),
])
)
})
it("filters price preferences by attribute", async () => {
const response = (
await api.get(
"/admin/price-preferences?attribute=region_id",
adminHeaders
)
).data.price_preferences

expect(response).toEqual([
expect.objectContaining({
attribute: "region_id",
value: "region-1",
is_tax_inclusive: true,
}),
])
})
})

describe("GET /admin/price-preferences/:id", () => {
it("returns a price preference by :id", async () => {
const response = (
await api.get(
`/admin/price-preferences/${pricePreference1.id}`,
adminHeaders
)
).data.price_preference

expect(response).toEqual(
expect.objectContaining({
attribute: "region_id",
value: "region-1",
is_tax_inclusive: true,
})
)
})
})

describe("POST /admin/price-preferences/:id", () => {
it("updates a price preference", async () => {
const response = (
await api.post(
`/admin/price-preferences/${pricePreference1.id}`,
{
attribute: "region_id",
value: "region-2",
is_tax_inclusive: false,
},
adminHeaders
)
).data.price_preference

expect(response).toEqual(
expect.objectContaining({
attribute: "region_id",
value: "region-2",
is_tax_inclusive: false,
})
)
})
it("updates the tax inclusivity in the price preference", async () => {
const response = (
await api.post(
`/admin/price-preferences/${pricePreference1.id}`,
{
is_tax_inclusive: false,
},
adminHeaders
)
).data.price_preference

expect(response).toEqual(
expect.objectContaining({
attribute: "region_id",
value: "region-1",
is_tax_inclusive: false,
})
)
})
})

describe("DELETE /admin/price-preferences/:id", () => {
it("Deletes a price preference", async () => {
const deleteResponse = await api.delete(
`/admin/price-preferences/${pricePreference1.id}`,
adminHeaders
)

const remainingPricePreferences = (
await api.get("/admin/price-preferences", adminHeaders)
).data.price_preferences

expect(deleteResponse.data).toEqual(
expect.objectContaining({
id: pricePreference1.id,
object: "price_preference",
deleted: true,
})
)

expect(remainingPricePreferences).toEqual([
expect.objectContaining({
attribute: "currency_code",
value: "EUR",
is_tax_inclusive: true,
}),
])
})
})
})
},
})
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ type OrderOutput =
metadata: any
}

export const getOrdersListlWorkflowId = "get-orders-list"
export const getOrdersListlWorkflow = createWorkflow(
getOrdersListlWorkflowId,
export const getOrdersListWorkflowId = "get-orders-list"
export const getOrdersListWorkflow = createWorkflow(
getOrdersListWorkflowId,
(
input: WorkflowData<{
fields: string[]
Expand Down
1 change: 1 addition & 0 deletions packages/core/core-flows/src/pricing/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from "./steps"
export * from "./workflows"
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { IPricingModuleService } from "@medusajs/types"
import { PricingWorkflow } from "@medusajs/types/dist/workflow"
import { ModuleRegistrationName } from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"

type StepInput = PricingWorkflow.CreatePricePreferencesWorkflowInput[]

export const createPricePreferencesStepId = "create-price-preferences"
export const createPricePreferencesStep = createStep(
createPricePreferencesStepId,
async (data: StepInput, { container }) => {
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)

const pricePreferences = await pricingModule.createPricePreferences(data)

return new StepResponse(
pricePreferences,
pricePreferences.map((pricePreference) => pricePreference.id)
)
},
async (pricePreferences, { container }) => {
if (!pricePreferences?.length) {
return
}

const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)

await pricingModule.deletePricePreferences(pricePreferences)
}
Comment on lines +23 to +33
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
async (pricePreferences, { container }) => {
if (!pricePreferences?.length) {
return
}
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
await pricingModule.deletePricePreferences(pricePreferences)
}
async (ids, { container }) => {
if (!ids?.length) {
return
}
const pricingModule = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)
await pricingModule.deletePricePreferences(ids)
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

damn the automerge was faster 😄 I'll open a new PR now anyway and address this.

)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { IPricingModuleService } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"

export const deletePricePreferencesStepId = "delete-price-preferences"
export const deletePricePreferencesStep = createStep(
deletePricePreferencesStepId,
async (ids: string[], { container }) => {
const service = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)

await service.softDeletePricePreferences(ids)

return new StepResponse(void 0, ids)
},
async (prevIds, { container }) => {
if (!prevIds?.length) {
return
}

const service = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)

await service.restorePricePreferences(prevIds)
}
)
3 changes: 3 additions & 0 deletions packages/core/core-flows/src/pricing/steps/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from "./create-price-sets"
export * from "./update-price-sets"
export * from "./create-price-preferences"
export * from "./update-price-preferences"
export * from "./delete-price-preferences"
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { PricingWorkflow, IPricingModuleService } from "@medusajs/types"
import {
ModuleRegistrationName,
getSelectsAndRelationsFromObjectArray,
} from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"

type StepInput = PricingWorkflow.UpdatePricePreferencesWorkflowInput

export const updatePricePreferencesStepId = "update-price-preferences"
export const updatePricePreferencesStep = createStep(
updatePricePreferencesStepId,
async (input: StepInput, { container }) => {
const service = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)

const { selects, relations } = getSelectsAndRelationsFromObjectArray([
input.update,
])

const prevData = await service.listPricePreferences(input.selector, {
select: selects,
relations,
})

const updatedPricePreferences = await service.updatePricePreferences(
input.selector,
input.update
)

return new StepResponse(updatedPricePreferences, prevData)
},
async (prevData, { container }) => {
if (!prevData?.length) {
return
}

const service = container.resolve<IPricingModuleService>(
ModuleRegistrationName.PRICING
)

await service.upsertPricePreferences(prevData)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

q: shouldn't this be update as well?

Copy link
Member Author

@sradevski sradevski Jul 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We pass the prevData as an array of entities, and only the Upsert method accepts such input. update is either an ID or a selector, which doesn't work for the reversal (we do this everywhere basically). I do think we might need to revisit the compensation methods in a lot of workflows and test them at the very least

}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { PricingWorkflow } from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { createPricePreferencesStep } from "../steps"

type WorkflowInputData = PricingWorkflow.CreatePricePreferencesWorkflowInput[]

export const createPricePreferencesWorkflowId = "create-price-preferences"
export const createPricePreferencesWorkflow = createWorkflow(
createPricePreferencesWorkflowId,
(input: WorkflowData<WorkflowInputData>) => {
return createPricePreferencesStep(input)
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { deletePricePreferencesStep } from "../steps"

export const deletePricePreferencesWorkflowId = "delete-price-preferences"
export const deletePricePreferencesWorkflow = createWorkflow(
deletePricePreferencesWorkflowId,
(input: WorkflowData<string[]>) => {
return deletePricePreferencesStep(input)
}
)
3 changes: 3 additions & 0 deletions packages/core/core-flows/src/pricing/workflows/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./create-price-preferences"
export * from "./update-price-preferences"
export * from "./delete-price-preferences"
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { PricingWorkflow } from "@medusajs/types"
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { updatePricePreferencesStep } from "../steps"

type WorkflowInputData = PricingWorkflow.UpdatePricePreferencesWorkflowInput

export const updatePricePreferencesWorkflowId = "update-price-preferences"
export const updatePricePreferencesWorkflow = createWorkflow(
updatePricePreferencesWorkflowId,
(input: WorkflowData<WorkflowInputData>) => {
return updatePricePreferencesStep(input)
}
)
Loading
Loading