feat(cart): Shipping method adjustments (#6119)
This commit is contained in:
5
.changeset/sixty-mice-sleep.md
Normal file
5
.changeset/sixty-mice-sleep.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@medusajs/types": patch
|
||||
---
|
||||
|
||||
feat(cart): Shipping method adjustments
|
||||
@@ -1005,6 +1005,7 @@ describe("Cart Module Service", () => {
|
||||
await service.setLineItemAdjustments(createdCart.id, [
|
||||
{
|
||||
id: adjustments[0].id,
|
||||
item_id: itemOne.id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
},
|
||||
@@ -1310,4 +1311,553 @@ describe("Cart Module Service", () => {
|
||||
expect(adjustments?.length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
describe("setShippingMethodAdjustments", () => {
|
||||
it("should set shipping method adjustments for a cart", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const [shippingMethodTwo] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 200,
|
||||
name: "test-2",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const adjustments = await service.setShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
{
|
||||
shipping_method_id: shippingMethodTwo.id,
|
||||
amount: 200,
|
||||
code: "FREE-2",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodTwo.id,
|
||||
amount: 200,
|
||||
code: "FREE-2",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should replace shipping method adjustments for a cart", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const adjustments = await service.setShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
await service.setShippingMethodAdjustments(createdCart.id, [
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
},
|
||||
])
|
||||
|
||||
const cart = await service.retrieve(createdCart.id, {
|
||||
relations: ["shipping_methods.adjustments"],
|
||||
})
|
||||
|
||||
expect(cart.shipping_methods).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: shippingMethodOne.id,
|
||||
cart_id: createdCart.id,
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(cart.shipping_methods?.length).toBe(1)
|
||||
expect(cart.shipping_methods?.[0].adjustments?.length).toBe(1)
|
||||
})
|
||||
|
||||
it("should remove all shipping method adjustments for a cart", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const adjustments = await service.setShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
await service.setShippingMethodAdjustments(createdCart.id, [])
|
||||
|
||||
const cart = await service.retrieve(createdCart.id, {
|
||||
relations: ["shipping_methods.adjustments"],
|
||||
})
|
||||
|
||||
expect(cart.shipping_methods).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: shippingMethodOne.id,
|
||||
adjustments: [],
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(cart.shipping_methods?.length).toBe(1)
|
||||
expect(cart.shipping_methods?.[0].adjustments?.length).toBe(0)
|
||||
})
|
||||
|
||||
it("should update shipping method adjustments for a cart", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const adjustments = await service.setShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
await service.setShippingMethodAdjustments(createdCart.id, [
|
||||
{
|
||||
id: adjustments[0].id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
},
|
||||
])
|
||||
|
||||
const cart = await service.retrieve(createdCart.id, {
|
||||
relations: ["shipping_methods.adjustments"],
|
||||
})
|
||||
|
||||
expect(cart.shipping_methods).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
id: shippingMethodOne.id,
|
||||
adjustments: [
|
||||
expect.objectContaining({
|
||||
id: adjustments[0].id,
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
])
|
||||
)
|
||||
|
||||
expect(cart.shipping_methods?.length).toBe(1)
|
||||
expect(cart.shipping_methods?.[0].adjustments?.length).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe("addShippingMethodAdjustments", () => {
|
||||
it("should add shipping method adjustments in a cart", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const adjustments = await service.addShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should add multiple shipping method adjustments for multiple shipping methods", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
const [shippingMethodTwo] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 200,
|
||||
name: "test-2",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const adjustments = await service.addShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
{
|
||||
shipping_method_id: shippingMethodTwo.id,
|
||||
amount: 150,
|
||||
code: "CODE-2",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodTwo.id,
|
||||
amount: 150,
|
||||
code: "CODE-2",
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should add shipping method adjustments for shipping methods on multiple carts", async () => {
|
||||
const [cartOne] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
const [cartTwo] = await service.create([
|
||||
{
|
||||
currency_code: "usd",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(cartOne.id, [
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
])
|
||||
const [shippingMethodTwo] = await service.addShippingMethods(cartTwo.id, [
|
||||
{
|
||||
amount: 200,
|
||||
name: "test-2",
|
||||
},
|
||||
])
|
||||
|
||||
await service.addShippingMethodAdjustments([
|
||||
// item from cart one
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
// item from cart two
|
||||
{
|
||||
shipping_method_id: shippingMethodTwo.id,
|
||||
amount: 150,
|
||||
code: "CODE-2",
|
||||
},
|
||||
])
|
||||
|
||||
const cartOneMethods = await service.listShippingMethods(
|
||||
{ cart_id: cartOne.id },
|
||||
{ relations: ["adjustments"] }
|
||||
)
|
||||
|
||||
const cartTwoMethods = await service.listShippingMethods(
|
||||
{ cart_id: cartTwo.id },
|
||||
{ relations: ["adjustments"] }
|
||||
)
|
||||
|
||||
expect(cartOneMethods).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
expect(cartTwoMethods).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
shipping_method_id: shippingMethodTwo.id,
|
||||
amount: 150,
|
||||
code: "CODE-2",
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
])
|
||||
)
|
||||
})
|
||||
|
||||
it("should throw if shipping method is not associated with cart", async () => {
|
||||
const [cartOne] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [cartTwo] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethodOne] = await service.addShippingMethods(cartOne.id, [
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
])
|
||||
|
||||
const error = await service
|
||||
.addShippingMethodAdjustments(cartTwo.id, [
|
||||
{
|
||||
shipping_method_id: shippingMethodOne.id,
|
||||
amount: 100,
|
||||
code: "FREE",
|
||||
},
|
||||
])
|
||||
.catch((e) => e)
|
||||
|
||||
expect(error.message).toBe(
|
||||
`Shipping method with id ${shippingMethodOne.id} does not exist on cart with id ${cartTwo.id}`
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe("removeShippingMethodAdjustments", () => {
|
||||
it("should remove a shipping method succesfully", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [method] = await service.addShippingMethods(createdCart.id, [
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
])
|
||||
|
||||
const [adjustment] = await service.addShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: method.id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustment.shipping_method_id).toBe(method.id)
|
||||
|
||||
await service.removeShippingMethodAdjustments(adjustment.id)
|
||||
|
||||
const adjustments = await service.listShippingMethodAdjustments({
|
||||
shipping_method_id: method.id,
|
||||
})
|
||||
|
||||
expect(adjustments?.length).toBe(0)
|
||||
})
|
||||
|
||||
it("should remove a shipping method succesfully with selector", async () => {
|
||||
const [createdCart] = await service.create([
|
||||
{
|
||||
currency_code: "eur",
|
||||
},
|
||||
])
|
||||
|
||||
const [shippingMethod] = await service.addShippingMethods(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
amount: 100,
|
||||
name: "test",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
const [adjustment] = await service.addShippingMethodAdjustments(
|
||||
createdCart.id,
|
||||
[
|
||||
{
|
||||
shipping_method_id: shippingMethod.id,
|
||||
amount: 50,
|
||||
code: "50%",
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expect(adjustment.shipping_method_id).toBe(shippingMethod.id)
|
||||
|
||||
await service.removeShippingMethodAdjustments({
|
||||
shipping_method_id: shippingMethod.id,
|
||||
})
|
||||
|
||||
const adjustments = await service.listShippingMethodAdjustments({
|
||||
shipping_method_id: shippingMethod.id,
|
||||
})
|
||||
|
||||
expect(adjustments?.length).toBe(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -4,6 +4,6 @@ export { default as LineItem } from "./line-item"
|
||||
export { default as LineItemAdjustment } from "./line-item-adjustment"
|
||||
export { default as LineItemTaxLine } from "./line-item-tax-line"
|
||||
export { default as ShippingMethod } from "./shipping-method"
|
||||
export { default as ShippingMethodAdjustmentLine } from "./shipping-method-adjustment-line"
|
||||
export { default as ShippingMethodAdjustment } from "./shipping-method-adjustment"
|
||||
export { default as ShippingMethodTaxLine } from "./shipping-method-tax-line"
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
import AdjustmentLine from "./adjustment-line"
|
||||
import LineItem from "./line-item"
|
||||
|
||||
@Entity({ tableName: "cart_line_item_adjustment_line" })
|
||||
@Entity({ tableName: "cart_line_item_adjustment" })
|
||||
@Check<LineItemAdjustment>({
|
||||
expression: (columns) => `${columns.amount} >= 0`,
|
||||
})
|
||||
@@ -18,7 +18,7 @@ export default class LineItemAdjustment extends AdjustmentLine {
|
||||
@ManyToOne(() => LineItem, {
|
||||
onDelete: "cascade",
|
||||
nullable: true,
|
||||
index: "IDX_adjustment_line_item_id",
|
||||
index: "IDX_adjustment_item_id",
|
||||
})
|
||||
item?: LineItem | null
|
||||
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import { generateEntityId } from "@medusajs/utils"
|
||||
import { BeforeCreate, Entity, ManyToOne, OnInit } from "@mikro-orm/core"
|
||||
import AdjustmentLine from "./adjustment-line"
|
||||
import ShippingMethod from "./shipping-method"
|
||||
|
||||
@Entity({ tableName: "cart_shipping_method_adjustment_line" })
|
||||
export default class ShippingMethodAdjustmentLine extends AdjustmentLine {
|
||||
@ManyToOne(() => ShippingMethod, {
|
||||
joinColumn: "shipping_method",
|
||||
fieldName: "shipping_method_id",
|
||||
})
|
||||
shipping_method: ShippingMethod
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "casmadj")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "casmadj")
|
||||
}
|
||||
}
|
||||
33
packages/cart/src/models/shipping-method-adjustment.ts
Normal file
33
packages/cart/src/models/shipping-method-adjustment.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { generateEntityId } from "@medusajs/utils"
|
||||
import {
|
||||
BeforeCreate,
|
||||
Entity,
|
||||
ManyToOne,
|
||||
OnInit,
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import AdjustmentLine from "./adjustment-line"
|
||||
import ShippingMethod from "./shipping-method"
|
||||
|
||||
@Entity({ tableName: "cart_shipping_method_adjustment" })
|
||||
export default class ShippingMethodAdjustment extends AdjustmentLine {
|
||||
@ManyToOne(() => ShippingMethod, {
|
||||
onDelete: "cascade",
|
||||
nullable: true,
|
||||
index: "IDX_adjustment_shipping_method_id",
|
||||
})
|
||||
shipping_method: ShippingMethod | null
|
||||
|
||||
@Property({ columnType: "text" })
|
||||
shipping_method_id: string
|
||||
|
||||
@BeforeCreate()
|
||||
onCreate() {
|
||||
this.id = generateEntityId(this.id, "casmadj")
|
||||
}
|
||||
|
||||
@OnInit()
|
||||
onInit() {
|
||||
this.id = generateEntityId(this.id, "casmadj")
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
Property,
|
||||
} from "@mikro-orm/core"
|
||||
import Cart from "./cart"
|
||||
import ShippingMethodAdjustmentLine from "./shipping-method-adjustment-line"
|
||||
import ShippingMethodAdjustment from "./shipping-method-adjustment"
|
||||
import ShippingMethodTaxLine from "./shipping-method-tax-line"
|
||||
|
||||
@Entity({ tableName: "cart_shipping_method" })
|
||||
@@ -62,13 +62,13 @@ export default class ShippingMethod {
|
||||
tax_lines = new Collection<ShippingMethodTaxLine>(this)
|
||||
|
||||
@OneToMany(
|
||||
() => ShippingMethodAdjustmentLine,
|
||||
() => ShippingMethodAdjustment,
|
||||
(adjustment) => adjustment.shipping_method,
|
||||
{
|
||||
cascade: [Cascade.REMOVE],
|
||||
}
|
||||
)
|
||||
adjustments = new Collection<ShippingMethodAdjustmentLine>(this)
|
||||
adjustments = new Collection<ShippingMethodAdjustment>(this)
|
||||
|
||||
/** COMPUTED PROPERTIES - START */
|
||||
|
||||
|
||||
@@ -15,7 +15,13 @@ import {
|
||||
isObject,
|
||||
isString,
|
||||
} from "@medusajs/utils"
|
||||
import { Cart, LineItem, LineItemAdjustment, ShippingMethod } from "@models"
|
||||
import {
|
||||
Cart,
|
||||
LineItem,
|
||||
LineItemAdjustment,
|
||||
ShippingMethod,
|
||||
ShippingMethodAdjustment,
|
||||
} from "@models"
|
||||
import { CreateLineItemDTO, UpdateLineItemDTO } from "@types"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import * as services from "../services"
|
||||
@@ -25,6 +31,7 @@ type InjectedDependencies = {
|
||||
cartService: services.CartService
|
||||
addressService: services.AddressService
|
||||
lineItemService: services.LineItemService
|
||||
shippingMethodAdjustmentService: services.ShippingMethodAdjustmentService
|
||||
shippingMethodService: services.ShippingMethodService
|
||||
lineItemAdjustmentService: services.LineItemAdjustmentService
|
||||
}
|
||||
@@ -34,6 +41,7 @@ export default class CartModuleService implements ICartModuleService {
|
||||
protected cartService_: services.CartService
|
||||
protected addressService_: services.AddressService
|
||||
protected lineItemService_: services.LineItemService
|
||||
protected shippingMethodAdjustmentService_: services.ShippingMethodAdjustmentService
|
||||
protected shippingMethodService_: services.ShippingMethodService
|
||||
protected lineItemAdjustmentService_: services.LineItemAdjustmentService
|
||||
|
||||
@@ -43,6 +51,7 @@ export default class CartModuleService implements ICartModuleService {
|
||||
cartService,
|
||||
addressService,
|
||||
lineItemService,
|
||||
shippingMethodAdjustmentService,
|
||||
shippingMethodService,
|
||||
lineItemAdjustmentService,
|
||||
}: InjectedDependencies,
|
||||
@@ -52,6 +61,7 @@ export default class CartModuleService implements ICartModuleService {
|
||||
this.cartService_ = cartService
|
||||
this.addressService_ = addressService
|
||||
this.lineItemService_ = lineItemService
|
||||
this.shippingMethodAdjustmentService_ = shippingMethodAdjustmentService
|
||||
this.shippingMethodService_ = shippingMethodService
|
||||
this.lineItemAdjustmentService_ = lineItemAdjustmentService
|
||||
}
|
||||
@@ -584,7 +594,7 @@ export default class CartModuleService implements ICartModuleService {
|
||||
): Promise<CartTypes.CartShippingMethodDTO[]>
|
||||
async addShippingMethods(
|
||||
cartId: string,
|
||||
methods: CartTypes.CreateShippingMethodDTO[],
|
||||
methods: CartTypes.CreateShippingMethodForSingleCartDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CartTypes.CartShippingMethodDTO[]>
|
||||
|
||||
@@ -618,9 +628,7 @@ export default class CartModuleService implements ICartModuleService {
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CartTypes.CartShippingMethodDTO[]
|
||||
>(methods, {
|
||||
populate: true,
|
||||
})
|
||||
>(methods, { populate: true })
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
@@ -882,4 +890,214 @@ export default class CartModuleService implements ICartModuleService {
|
||||
|
||||
await this.lineItemAdjustmentService_.delete(ids, sharedContext)
|
||||
}
|
||||
|
||||
@InjectManager("baseRepository_")
|
||||
async listShippingMethodAdjustments(
|
||||
filters: CartTypes.FilterableShippingMethodAdjustmentProps = {},
|
||||
config: FindConfig<CartTypes.ShippingMethodAdjustmentDTO> = {},
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
) {
|
||||
const adjustments = await this.shippingMethodAdjustmentService_.list(
|
||||
filters,
|
||||
config,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CartTypes.ShippingMethodAdjustmentDTO[]
|
||||
>(adjustments, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async setShippingMethodAdjustments(
|
||||
cartId: string,
|
||||
adjustments: (
|
||||
| CartTypes.CreateShippingMethodAdjustmentDTO
|
||||
| CartTypes.UpdateShippingMethodAdjustmentDTO
|
||||
)[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<CartTypes.ShippingMethodAdjustmentDTO[]> {
|
||||
const cart = await this.retrieve(
|
||||
cartId,
|
||||
{ select: ["id"], relations: ["shipping_methods.adjustments"] },
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const methodIds = cart.shipping_methods?.map((method) => method.id)
|
||||
|
||||
const existingAdjustments = await this.listShippingMethodAdjustments(
|
||||
{ shipping_method_id: methodIds ?? [] },
|
||||
{ select: ["id"] },
|
||||
sharedContext
|
||||
)
|
||||
|
||||
let toUpdate: CartTypes.UpdateShippingMethodAdjustmentDTO[] = []
|
||||
let toCreate: CartTypes.CreateShippingMethodAdjustmentDTO[] = []
|
||||
for (const adj of adjustments) {
|
||||
if ("id" in adj) {
|
||||
toUpdate.push(adj as CartTypes.UpdateShippingMethodAdjustmentDTO)
|
||||
} else {
|
||||
toCreate.push(adj as CartTypes.CreateShippingMethodAdjustmentDTO)
|
||||
}
|
||||
}
|
||||
|
||||
const adjustmentsSet = new Set(toUpdate.map((a) => a.id))
|
||||
|
||||
const toDelete: CartTypes.ShippingMethodAdjustmentDTO[] = []
|
||||
|
||||
// From the existing adjustments, find the ones that are not passed in adjustments
|
||||
existingAdjustments.forEach(
|
||||
(adj: CartTypes.ShippingMethodAdjustmentDTO) => {
|
||||
if (!adjustmentsSet.has(adj.id)) {
|
||||
toDelete.push(adj)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
if (toDelete.length) {
|
||||
await this.shippingMethodAdjustmentService_.delete(
|
||||
toDelete.map((adj) => adj!.id),
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
|
||||
let result: ShippingMethodAdjustment[] = []
|
||||
|
||||
if (toCreate.length) {
|
||||
const created = await this.shippingMethodAdjustmentService_.create(
|
||||
toCreate,
|
||||
sharedContext
|
||||
)
|
||||
|
||||
result.push(...created)
|
||||
}
|
||||
|
||||
if (toUpdate.length) {
|
||||
const updated = await this.shippingMethodAdjustmentService_.update(
|
||||
toUpdate,
|
||||
sharedContext
|
||||
)
|
||||
result.push(...updated)
|
||||
}
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CartTypes.ShippingMethodAdjustmentDTO[]
|
||||
>(result, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
async addShippingMethodAdjustments(
|
||||
adjustments: CartTypes.CreateShippingMethodAdjustmentDTO[]
|
||||
): Promise<CartTypes.ShippingMethodAdjustmentDTO[]>
|
||||
async addShippingMethodAdjustments(
|
||||
adjustment: CartTypes.CreateShippingMethodAdjustmentDTO
|
||||
): Promise<CartTypes.ShippingMethodAdjustmentDTO>
|
||||
async addShippingMethodAdjustments(
|
||||
cartId: string,
|
||||
adjustments: CartTypes.CreateShippingMethodAdjustmentDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CartTypes.ShippingMethodAdjustmentDTO[]>
|
||||
|
||||
@InjectTransactionManager("baseRepository_")
|
||||
async addShippingMethodAdjustments(
|
||||
cartIdOrData:
|
||||
| string
|
||||
| CartTypes.CreateShippingMethodAdjustmentDTO[]
|
||||
| CartTypes.CreateShippingMethodAdjustmentDTO,
|
||||
adjustments?: CartTypes.CreateShippingMethodAdjustmentDTO[],
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<
|
||||
| CartTypes.ShippingMethodAdjustmentDTO[]
|
||||
| CartTypes.ShippingMethodAdjustmentDTO
|
||||
> {
|
||||
let addedAdjustments: ShippingMethodAdjustment[] = []
|
||||
if (isString(cartIdOrData)) {
|
||||
const cart = await this.retrieve(
|
||||
cartIdOrData,
|
||||
{ select: ["id"], relations: ["shipping_methods"] },
|
||||
sharedContext
|
||||
)
|
||||
|
||||
const methodIds = cart.shipping_methods?.map((method) => method.id)
|
||||
|
||||
for (const adj of adjustments || []) {
|
||||
if (!methodIds?.includes(adj.shipping_method_id)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Shipping method with id ${adj.shipping_method_id} does not exist on cart with id ${cartIdOrData}`
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
addedAdjustments = await this.shippingMethodAdjustmentService_.create(
|
||||
adjustments as CartTypes.CreateShippingMethodAdjustmentDTO[],
|
||||
sharedContext
|
||||
)
|
||||
} else {
|
||||
const data = Array.isArray(cartIdOrData) ? cartIdOrData : [cartIdOrData]
|
||||
|
||||
addedAdjustments = await this.shippingMethodAdjustmentService_.create(
|
||||
data as CartTypes.CreateShippingMethodAdjustmentDTO[],
|
||||
sharedContext
|
||||
)
|
||||
}
|
||||
|
||||
if (isObject(cartIdOrData)) {
|
||||
return await this.baseRepository_.serialize<CartTypes.ShippingMethodAdjustmentDTO>(
|
||||
addedAdjustments[0],
|
||||
{
|
||||
populate: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return await this.baseRepository_.serialize<
|
||||
CartTypes.ShippingMethodAdjustmentDTO[]
|
||||
>(addedAdjustments, {
|
||||
populate: true,
|
||||
})
|
||||
}
|
||||
|
||||
async removeShippingMethodAdjustments(
|
||||
adjustmentIds: string[],
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
async removeShippingMethodAdjustments(
|
||||
adjustmentId: string,
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
async removeShippingMethodAdjustments(
|
||||
selector: Partial<CartTypes.ShippingMethodAdjustmentDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
|
||||
async removeShippingMethodAdjustments(
|
||||
adjustmentIdsOrSelector:
|
||||
| string
|
||||
| string[]
|
||||
| Partial<CartTypes.ShippingMethodAdjustmentDTO>,
|
||||
@MedusaContext() sharedContext: Context = {}
|
||||
): Promise<void> {
|
||||
let ids: string[] = []
|
||||
if (isObject(adjustmentIdsOrSelector)) {
|
||||
const adjustments = await this.listShippingMethodAdjustments(
|
||||
{
|
||||
...adjustmentIdsOrSelector,
|
||||
} as Partial<CartTypes.ShippingMethodAdjustmentDTO>,
|
||||
{ select: ["id"] },
|
||||
sharedContext
|
||||
)
|
||||
|
||||
ids = adjustments.map((adj) => adj.id)
|
||||
} else {
|
||||
ids = Array.isArray(adjustmentIdsOrSelector)
|
||||
? adjustmentIdsOrSelector
|
||||
: [adjustmentIdsOrSelector]
|
||||
}
|
||||
|
||||
await this.shippingMethodAdjustmentService_.delete(ids, sharedContext)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ export { default as CartModuleService } from "./cart-module"
|
||||
export { default as LineItemService } from "./line-item"
|
||||
export { default as LineItemAdjustmentService } from "./line-item-adjustment"
|
||||
export { default as ShippingMethodService } from "./shipping-method"
|
||||
export { default as ShippingMethodAdjustmentService } from "./shipping-method-adjustment"
|
||||
|
||||
|
||||
26
packages/cart/src/services/shipping-method-adjustment.ts
Normal file
26
packages/cart/src/services/shipping-method-adjustment.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { ModulesSdkUtils } from "@medusajs/utils"
|
||||
import { ShippingMethodAdjustment } from "@models"
|
||||
import {
|
||||
CreateShippingMethodAdjustmentDTO,
|
||||
UpdateShippingMethodAdjustmentDTO,
|
||||
} from "@types"
|
||||
|
||||
type InjectedDependencies = {
|
||||
shippingMethodAdjustmentRepository: DAL.RepositoryService
|
||||
}
|
||||
|
||||
export default class ShippingMethodAdjustmentService<
|
||||
TEntity extends ShippingMethodAdjustment = ShippingMethodAdjustment
|
||||
> extends ModulesSdkUtils.abstractServiceFactory<
|
||||
InjectedDependencies,
|
||||
{
|
||||
create: CreateShippingMethodAdjustmentDTO
|
||||
update: UpdateShippingMethodAdjustmentDTO
|
||||
}
|
||||
>(ShippingMethodAdjustment)<TEntity> {
|
||||
constructor(container: InjectedDependencies) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,9 @@ export * from "./address"
|
||||
export * from "./cart"
|
||||
export * from "./line-item"
|
||||
export * from "./line-item-adjustment"
|
||||
export * from "./shipping-method"
|
||||
export * from "./repositories"
|
||||
export * from "./shipping-method"
|
||||
export * from "./shipping-method-adjustment"
|
||||
|
||||
export type InitializeModuleInjectableDependencies = {
|
||||
logger?: Logger
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import { DAL } from "@medusajs/types"
|
||||
import { Cart, LineItem, LineItemAdjustment, ShippingMethod } from "@models"
|
||||
import {
|
||||
Cart,
|
||||
LineItem,
|
||||
LineItemAdjustment,
|
||||
ShippingMethod,
|
||||
ShippingMethodAdjustment,
|
||||
} from "@models"
|
||||
import { CreateAddressDTO, UpdateAddressDTO } from "./address"
|
||||
import { CreateCartDTO, UpdateCartDTO } from "./cart"
|
||||
import { CreateLineItemDTO, UpdateLineItemDTO } from "./line-item"
|
||||
@@ -11,6 +17,10 @@ import {
|
||||
CreateShippingMethodDTO,
|
||||
UpdateShippingMethodDTO,
|
||||
} from "./shipping-method"
|
||||
import {
|
||||
CreateShippingMethodAdjustmentDTO,
|
||||
UpdateShippingMethodAdjustmentDTO,
|
||||
} from "./shipping-method-adjustment"
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface IAddressRepository<TEntity extends Cart = Cart>
|
||||
@@ -62,3 +72,13 @@ export interface ILineItemAdjustmentRepository<
|
||||
update: UpdateLineItemAdjustmentDTO
|
||||
}
|
||||
> {}
|
||||
|
||||
export interface IShippingMethodAdjustmentRepository<
|
||||
TEntity extends ShippingMethodAdjustment = ShippingMethodAdjustment
|
||||
> extends DAL.RepositoryService<
|
||||
TEntity,
|
||||
{
|
||||
create: CreateShippingMethodAdjustmentDTO
|
||||
update: UpdateShippingMethodAdjustmentDTO
|
||||
}
|
||||
> {}
|
||||
|
||||
17
packages/cart/src/types/shipping-method-adjustment.ts
Normal file
17
packages/cart/src/types/shipping-method-adjustment.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export interface CreateShippingMethodAdjustmentDTO {
|
||||
shipping_method_id: string
|
||||
code: string
|
||||
amount: number
|
||||
description?: string
|
||||
promotion_id?: string
|
||||
provider_id?: string
|
||||
}
|
||||
|
||||
export interface UpdateShippingMethodAdjustmentDTO {
|
||||
id: string
|
||||
code?: string
|
||||
amount?: number
|
||||
description?: string
|
||||
promotion_id?: string
|
||||
provider_id?: string
|
||||
}
|
||||
@@ -40,11 +40,15 @@ export interface AdjustmentLineDTO {
|
||||
updated_at: Date | string
|
||||
}
|
||||
|
||||
export interface ShippingMethodAdjustmentLineDTO extends AdjustmentLineDTO {
|
||||
export interface ShippingMethodAdjustmentDTO extends AdjustmentLineDTO {
|
||||
/**
|
||||
* The associated shipping method
|
||||
*/
|
||||
shipping_method: CartShippingMethodDTO
|
||||
/**
|
||||
* The ID of the associated shipping method
|
||||
*/
|
||||
shipping_method_id: string
|
||||
}
|
||||
|
||||
export interface LineItemAdjustmentDTO extends AdjustmentLineDTO {
|
||||
@@ -227,7 +231,7 @@ export interface CartShippingMethodDTO {
|
||||
*
|
||||
* @expandable
|
||||
*/
|
||||
adjustments?: ShippingMethodAdjustmentLineDTO[]
|
||||
adjustments?: ShippingMethodAdjustmentDTO[]
|
||||
|
||||
/**
|
||||
* When the shipping method was created.
|
||||
@@ -518,6 +522,14 @@ export interface FilterableShippingMethodProps
|
||||
shipping_option_id?: string | string[]
|
||||
}
|
||||
|
||||
export interface FilterableShippingMethodAdjustmentProps
|
||||
extends BaseFilterable<FilterableShippingMethodAdjustmentProps> {
|
||||
id?: string | string[]
|
||||
shipping_method_id?: string | string[]
|
||||
promotion_id?: string | string[]
|
||||
provider_id?: string | string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Remove this in favor of CartDTO, when module is released
|
||||
* @deprecated Use CartDTO instead
|
||||
|
||||
@@ -208,4 +208,22 @@ export interface UpdateShippingMethodDTO {
|
||||
adjustments?: CreateAdjustmentDTO[] | UpdateAdjustmentDTO[]
|
||||
}
|
||||
|
||||
export interface CreateShippingMethodAdjustmentDTO {
|
||||
shipping_method_id: string
|
||||
code: string
|
||||
amount: number
|
||||
description?: string
|
||||
promotion_id?: string
|
||||
provider_id?: string
|
||||
}
|
||||
|
||||
export interface UpdateShippingMethodAdjustmentDTO {
|
||||
id: string
|
||||
code?: string
|
||||
amount?: number
|
||||
description?: string
|
||||
promotion_id?: string
|
||||
provider_id?: string
|
||||
}
|
||||
|
||||
/** SHIPPING METHODS END */
|
||||
|
||||
@@ -2,29 +2,34 @@ import { FindConfig } from "../common"
|
||||
import { IModuleService } from "../modules-sdk"
|
||||
import { Context } from "../shared-context"
|
||||
import {
|
||||
CartAddressDTO,
|
||||
CartDTO,
|
||||
CartLineItemDTO,
|
||||
CartShippingMethodDTO,
|
||||
FilterableAddressProps,
|
||||
FilterableCartProps,
|
||||
FilterableLineItemAdjustmentProps,
|
||||
FilterableLineItemProps,
|
||||
FilterableShippingMethodProps,
|
||||
LineItemAdjustmentDTO,
|
||||
CartAddressDTO,
|
||||
CartDTO,
|
||||
CartLineItemDTO,
|
||||
CartShippingMethodDTO,
|
||||
FilterableAddressProps,
|
||||
FilterableCartProps,
|
||||
FilterableLineItemAdjustmentProps,
|
||||
FilterableLineItemProps,
|
||||
FilterableShippingMethodAdjustmentProps,
|
||||
FilterableShippingMethodProps,
|
||||
LineItemAdjustmentDTO,
|
||||
ShippingMethodAdjustmentDTO,
|
||||
} from "./common"
|
||||
import {
|
||||
CreateAddressDTO,
|
||||
CreateAdjustmentDTO,
|
||||
CreateCartDTO,
|
||||
CreateLineItemDTO,
|
||||
CreateLineItemForCartDTO,
|
||||
CreateShippingMethodDTO,
|
||||
UpdateAddressDTO,
|
||||
UpdateCartDTO,
|
||||
UpdateLineItemDTO,
|
||||
UpdateLineItemWithSelectorDTO,
|
||||
UpsertLineItemAdjustmentDTO
|
||||
CreateAddressDTO,
|
||||
CreateAdjustmentDTO,
|
||||
CreateCartDTO,
|
||||
CreateLineItemDTO,
|
||||
CreateLineItemForCartDTO,
|
||||
CreateShippingMethodAdjustmentDTO,
|
||||
CreateShippingMethodDTO,
|
||||
CreateShippingMethodForSingleCartDTO,
|
||||
UpdateAddressDTO,
|
||||
UpdateCartDTO,
|
||||
UpdateLineItemDTO,
|
||||
UpdateLineItemWithSelectorDTO,
|
||||
UpdateShippingMethodAdjustmentDTO,
|
||||
UpsertLineItemAdjustmentDTO,
|
||||
} from "./mutations"
|
||||
|
||||
export interface ICartModuleService extends IModuleService {
|
||||
@@ -126,7 +131,7 @@ export interface ICartModuleService extends IModuleService {
|
||||
listShippingMethods(
|
||||
filters: FilterableShippingMethodProps,
|
||||
config: FindConfig<CartShippingMethodDTO>,
|
||||
sharedContext: Context
|
||||
sharedContext?: Context
|
||||
): Promise<CartShippingMethodDTO[]>
|
||||
|
||||
addShippingMethods(
|
||||
@@ -137,7 +142,7 @@ export interface ICartModuleService extends IModuleService {
|
||||
): Promise<CartShippingMethodDTO[]>
|
||||
addShippingMethods(
|
||||
cartId: string,
|
||||
methods: CreateShippingMethodDTO[],
|
||||
methods: CreateShippingMethodForSingleCartDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<CartShippingMethodDTO[]>
|
||||
|
||||
@@ -189,4 +194,44 @@ export interface ICartModuleService extends IModuleService {
|
||||
selector: Partial<LineItemAdjustmentDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
|
||||
listShippingMethodAdjustments(
|
||||
filters: FilterableShippingMethodAdjustmentProps,
|
||||
config?: FindConfig<ShippingMethodAdjustmentDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingMethodAdjustmentDTO[]>
|
||||
|
||||
addShippingMethodAdjustments(
|
||||
data: CreateShippingMethodAdjustmentDTO[]
|
||||
): Promise<ShippingMethodAdjustmentDTO[]>
|
||||
addShippingMethodAdjustments(
|
||||
data: CreateShippingMethodAdjustmentDTO
|
||||
): Promise<ShippingMethodAdjustmentDTO>
|
||||
addShippingMethodAdjustments(
|
||||
cartId: string,
|
||||
data: CreateShippingMethodAdjustmentDTO[],
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingMethodAdjustmentDTO[]>
|
||||
|
||||
setShippingMethodAdjustments(
|
||||
cartId: string,
|
||||
data: (
|
||||
| CreateShippingMethodAdjustmentDTO
|
||||
| UpdateShippingMethodAdjustmentDTO
|
||||
)[],
|
||||
sharedContext?: Context
|
||||
): Promise<ShippingMethodAdjustmentDTO[]>
|
||||
|
||||
removeShippingMethodAdjustments(
|
||||
adjustmentIds: string[],
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
removeShippingMethodAdjustments(
|
||||
adjustmentId: string,
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
removeShippingMethodAdjustments(
|
||||
selector: Partial<ShippingMethodAdjustmentDTO>,
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user