Skip to content

Commit

Permalink
feat: Add HTTP endpoints and workflows for price preference management (
Browse files Browse the repository at this point in the history
#7960)

REF CORE-2376

Remaining pieces are adding UI to manage the flag, showing the flag in price editor, plugging it in cart calculations, and #7827
  • Loading branch information
sradevski authored Jul 5, 2024
1 parent 1162b16 commit 3e86cb6
Show file tree
Hide file tree
Showing 27 changed files with 702 additions and 10 deletions.
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)
}
)
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)
}
)
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

0 comments on commit 3e86cb6

Please sign in to comment.