feat(utils,types): campaigns and campaign budgets + services CRUD (#6063)

* chore: added item/shipping adjustments for order/items/shipping_methods

* chore: add validation for order type and target rules

* chore: add comment for applied promotions

* chore: add shipping method and item adjustments

* chore: include applied promotions to items/shipping_method for each case

* chore: handle case for items across and order to consider existing applications

* chore: handle case for applied promo values to shipping => across

* chore: added changeset

* chore: update return of function

* chore: campaigns and campaign budgets + services CRUD

* Apply suggestions from code review

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>

* chore: minor refactor

* chore: added single/bulk interfaces

* Apply suggestions from code review

Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>

* chore: use DAL date entity

* chore: align nullable

* Update packages/promotion/src/models/promotion-rule.ts

* chore: fix types

* chore: review changes

* Update packages/promotion/src/utils/compute-actions/shipping-methods.ts

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>

---------

Co-authored-by: Oli Juhl <59018053+olivermrbl@users.noreply.github.com>
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
This commit is contained in:
Riqwan Thamir
2024-01-12 14:14:34 +01:00
committed by GitHub
co-authored by Oli Juhl Philip Korsholm
parent b782d3bcb7
commit fade8ea7bf
29 changed files with 1181 additions and 28 deletions
@@ -0,0 +1,241 @@
import { IPromotionModuleService } from "@medusajs/types"
import { SqlEntityManager } from "@mikro-orm/postgresql"
import { initialize } from "../../../../src"
import { createCampaigns } from "../../../__fixtures__/campaigns"
import { DB_URL, MikroOrmWrapper } from "../../../utils"
jest.setTimeout(30000)
describe("Promotion Module Service: Campaigns", () => {
let service: IPromotionModuleService
let repositoryManager: SqlEntityManager
beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()
repositoryManager = MikroOrmWrapper.forkManager()
service = await initialize({
database: {
clientUrl: DB_URL,
schema: process.env.MEDUSA_PROMOTION_DB_SCHEMA,
},
})
})
afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
})
describe("createCampaigns", () => {
it("should throw an error when required params are not passed", async () => {
const error = await service
.createCampaigns([
{
name: "test",
} as any,
])
.catch((e) => e)
expect(error.message).toContain(
"Value for Campaign.campaign_identifier is required, 'undefined' found"
)
})
it("should create a basic campaign successfully", async () => {
const startsAt = new Date("01/01/2024")
const endsAt = new Date("01/01/2025")
const [createdCampaign] = await service.createCampaigns([
{
name: "test",
campaign_identifier: "test",
starts_at: startsAt,
ends_at: endsAt,
},
])
const campaign = await service.retrieveCampaign(createdCampaign.id)
expect(campaign).toEqual(
expect.objectContaining({
name: "test",
campaign_identifier: "test",
starts_at: startsAt,
ends_at: endsAt,
})
)
})
it("should create a campaign with campaign budget successfully", async () => {
const startsAt = new Date("01/01/2024")
const endsAt = new Date("01/01/2025")
const [createdPromotion] = await service.createCampaigns([
{
name: "test",
campaign_identifier: "test",
starts_at: startsAt,
ends_at: endsAt,
budget: {
limit: 1000,
type: "usage",
used: 10,
},
},
])
const campaign = await service.retrieveCampaign(createdPromotion.id, {
relations: ["budget"],
})
expect(campaign).toEqual(
expect.objectContaining({
name: "test",
campaign_identifier: "test",
starts_at: startsAt,
ends_at: endsAt,
budget: expect.objectContaining({
limit: 1000,
type: "usage",
used: 10,
}),
})
)
})
})
describe("updateCampaigns", () => {
it("should throw an error when required params are not passed", async () => {
const error = await service
.updateCampaigns([
{
name: "test",
} as any,
])
.catch((e) => e)
expect(error.message).toContain('Campaign with id "" not found')
})
it("should update the attributes of a campaign successfully", async () => {
await createCampaigns(repositoryManager)
const [updatedCampaign] = await service.updateCampaigns([
{
id: "campaign-id-1",
description: "test description 1",
currency: "EUR",
campaign_identifier: "new",
starts_at: new Date("01/01/2024"),
ends_at: new Date("01/01/2025"),
},
])
expect(updatedCampaign).toEqual(
expect.objectContaining({
description: "test description 1",
currency: "EUR",
campaign_identifier: "new",
starts_at: new Date("01/01/2024"),
ends_at: new Date("01/01/2025"),
})
)
})
it("should update the attributes of a campaign budget successfully", async () => {
await createCampaigns(repositoryManager)
const [updatedCampaign] = await service.updateCampaigns([
{
id: "campaign-id-1",
budget: {
limit: 100,
used: 100,
},
},
])
expect(updatedCampaign).toEqual(
expect.objectContaining({
budget: expect.objectContaining({
limit: 100,
used: 100,
}),
})
)
})
})
describe("retrieveCampaign", () => {
beforeEach(async () => {
await createCampaigns(repositoryManager)
})
const id = "campaign-id-1"
it("should return campaign for the given id", async () => {
const campaign = await service.retrieveCampaign(id)
expect(campaign).toEqual(
expect.objectContaining({
id,
})
)
})
it("should throw an error when campaign with id does not exist", async () => {
let error
try {
await service.retrieveCampaign("does-not-exist")
} catch (e) {
error = e
}
expect(error.message).toEqual(
"Campaign with id: does-not-exist was not found"
)
})
it("should throw an error when a id is not provided", async () => {
let error
try {
await service.retrieveCampaign(undefined as unknown as string)
} catch (e) {
error = e
}
expect(error.message).toEqual('"campaignId" must be defined')
})
it("should return campaign based on config select param", async () => {
const campaign = await service.retrieveCampaign(id, {
select: ["id"],
})
const serialized = JSON.parse(JSON.stringify(campaign))
expect(serialized).toEqual({
id,
})
})
})
describe("deleteCampaigns", () => {
beforeEach(async () => {
await createCampaigns(repositoryManager)
})
const id = "campaign-id-1"
it("should delete the campaigns given an id successfully", async () => {
await service.deleteCampaigns([id])
const campaigns = await service.list({
id: [id],
})
expect(campaigns).toHaveLength(0)
})
})
})