feat(medusa): Preserve custom adjustments when refreshing adjustments (#3085)
This commit is contained in:
1 parent
d0adaf57ed
commit
5b63533c77
10 files changed
+299
-41
No files matched your search
@@ -21,6 +21,7 @@ import { ShippingOptionServiceMock } from "../__mocks__/shipping-option"
|
||||
import { CustomerServiceMock } from "../__mocks__/customer"
|
||||
import TaxCalculationStrategy from "../../strategies/tax-calculation"
|
||||
import SystemTaxService from "../system-tax"
|
||||
import { IsNull, Not } from "typeorm"
|
||||
|
||||
const eventBusService = {
|
||||
emit: jest.fn(),
|
||||
@@ -515,6 +516,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: [IdMap.getId("merger")],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -745,6 +747,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: [IdMap.getId("itemToRemove")],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -786,6 +789,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: [IdMap.getId("itemToRemove")],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -965,6 +969,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: [IdMap.getId("existingUpdate")],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -2259,6 +2264,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: ["li1", "li2"],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -2309,6 +2315,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: ["li1", "li2"],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -2368,6 +2375,7 @@ describe("CartService", () => {
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||
item_id: ["li1", "li2"],
|
||||
discount_id: expect.objectContaining(Not(IsNull())),
|
||||
})
|
||||
|
||||
expect(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { isEmpty, isEqual } from "lodash"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { DeepPartial, EntityManager, In } from "typeorm"
|
||||
import { DeepPartial, EntityManager, In, IsNull, Not } from "typeorm"
|
||||
import { IPriceSelectionStrategy, TransactionBaseService } from "../interfaces"
|
||||
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
|
||||
import {
|
||||
@@ -2604,6 +2604,7 @@ class CartService extends TransactionBaseService {
|
||||
.withTransaction(transactionManager)
|
||||
.delete({
|
||||
item_id: nonReturnLineIDs,
|
||||
discount_id: Not(IsNull()),
|
||||
})
|
||||
|
||||
// potentially create/update line item adjustments
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { EntityManager, In } from "typeorm"
|
||||
import { EntityManager, FindOperator, In } from "typeorm"
|
||||
|
||||
import { Cart, DiscountRuleType, LineItem, LineItemAdjustment } from "../models"
|
||||
import { LineItemAdjustmentRepository } from "../repositories/line-item-adjustment"
|
||||
@@ -153,7 +153,12 @@ class LineItemAdjustmentService extends TransactionBaseService {
|
||||
* @return the result of the delete operation
|
||||
*/
|
||||
async delete(
|
||||
selectorOrIds: string | string[] | FilterableLineItemAdjustmentProps
|
||||
selectorOrIds:
|
||||
| string
|
||||
| string[]
|
||||
| (FilterableLineItemAdjustmentProps & {
|
||||
discount_id?: FindOperator<string | null>
|
||||
})
|
||||
): Promise<void> {
|
||||
return this.atomicPhase_(async (manager) => {
|
||||
const lineItemAdjustmentRepo: LineItemAdjustmentRepository =
|
||||
|
||||
@@ -373,7 +373,9 @@ export default class OrderEditService extends TransactionBaseService {
|
||||
quantity: data.quantity,
|
||||
})
|
||||
|
||||
await this.refreshAdjustments(orderEditId)
|
||||
await this.refreshAdjustments(orderEditId, {
|
||||
preserveCustomAdjustments: true,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -434,7 +436,10 @@ export default class OrderEditService extends TransactionBaseService {
|
||||
})
|
||||
}
|
||||
|
||||
async refreshAdjustments(orderEditId: string) {
|
||||
async refreshAdjustments(
|
||||
orderEditId: string,
|
||||
config = { preserveCustomAdjustments: false }
|
||||
) {
|
||||
const manager = this.transactionManager_ ?? this.manager_
|
||||
|
||||
const lineItemAdjustmentServiceTx =
|
||||
@@ -461,7 +466,13 @@ export default class OrderEditService extends TransactionBaseService {
|
||||
orderEdit.items.forEach((item) => {
|
||||
if (item.adjustments?.length) {
|
||||
item.adjustments.forEach((adjustment) => {
|
||||
clonedItemAdjustmentIds.push(adjustment.id)
|
||||
const preserveAdjustment = config.preserveCustomAdjustments
|
||||
? !!adjustment.discount_id
|
||||
: true
|
||||
|
||||
if (preserveAdjustment) {
|
||||
clonedItemAdjustmentIds.push(adjustment.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -447,26 +447,28 @@ class TotalsService extends TransactionBaseService {
|
||||
const allocationMap: LineAllocationsMap = {}
|
||||
|
||||
if (!options.exclude_discounts) {
|
||||
let lineDiscounts: LineDiscountAmount[] = []
|
||||
|
||||
const discount = orderOrCart.discounts?.find(
|
||||
({ rule }) => rule.type !== DiscountRuleType.FREE_SHIPPING
|
||||
)
|
||||
if (discount) {
|
||||
lineDiscounts = this.getLineDiscounts(orderOrCart, discount)
|
||||
}
|
||||
|
||||
const lineDiscounts: LineDiscountAmount[] = this.getLineDiscounts(
|
||||
orderOrCart,
|
||||
discount
|
||||
)
|
||||
|
||||
for (const ld of lineDiscounts) {
|
||||
const adjustmentAmount = ld.amount + ld.customAdjustmentsAmount
|
||||
|
||||
if (allocationMap[ld.item.id]) {
|
||||
allocationMap[ld.item.id].discount = {
|
||||
amount: ld.amount,
|
||||
unit_amount: Math.round(ld.amount / ld.item.quantity),
|
||||
amount: adjustmentAmount,
|
||||
unit_amount: Math.round(adjustmentAmount / ld.item.quantity),
|
||||
}
|
||||
} else {
|
||||
allocationMap[ld.item.id] = {
|
||||
discount: {
|
||||
amount: ld.amount,
|
||||
unit_amount: Math.round(ld.amount / ld.item.quantity),
|
||||
amount: adjustmentAmount,
|
||||
unit_amount: Math.round(adjustmentAmount / ld.item.quantity),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -717,7 +719,7 @@ class TotalsService extends TransactionBaseService {
|
||||
swaps?: Swap[]
|
||||
claims?: ClaimOrder[]
|
||||
},
|
||||
discount: Discount
|
||||
discount?: Discount
|
||||
): LineDiscountAmount[] {
|
||||
let merged: LineItem[] = [...(cartOrOrder.items ?? [])]
|
||||
|
||||
@@ -736,18 +738,24 @@ class TotalsService extends TransactionBaseService {
|
||||
|
||||
return merged.map((item) => {
|
||||
const adjustments = item?.adjustments || []
|
||||
const discountAdjustments = adjustments.filter(
|
||||
(adjustment) => adjustment.discount_id === discount.id
|
||||
const discountAdjustments = discount
|
||||
? adjustments.filter(
|
||||
(adjustment) => adjustment.discount_id === discount.id
|
||||
)
|
||||
: []
|
||||
|
||||
const customAdjustments = adjustments.filter(
|
||||
(adjustment) => adjustment.discount_id === null
|
||||
)
|
||||
|
||||
const sumAdjustments = (total, adjustment) => total + adjustment.amount
|
||||
|
||||
return {
|
||||
item,
|
||||
amount: item.allow_discounts
|
||||
? discountAdjustments.reduce(
|
||||
(total, adjustment) => total + adjustment.amount,
|
||||
0
|
||||
)
|
||||
? discountAdjustments.reduce(sumAdjustments, 0)
|
||||
: 0,
|
||||
customAdjustmentsAmount: customAdjustments.reduce(sumAdjustments, 0),
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -994,16 +1002,6 @@ class TotalsService extends TransactionBaseService {
|
||||
excludeNonDiscounts: true,
|
||||
})
|
||||
|
||||
// we only support having free shipping and one other discount, so first
|
||||
// find the discount, which is not free shipping.
|
||||
const discount = cartOrOrder.discounts?.find(
|
||||
({ rule }) => rule.type !== DiscountRuleType.FREE_SHIPPING
|
||||
)
|
||||
|
||||
if (!discount) {
|
||||
return 0
|
||||
}
|
||||
|
||||
const discountTotal = this.getLineItemAdjustmentsTotal(cartOrOrder)
|
||||
|
||||
if (subtotal < 0) {
|
||||
|
||||
@@ -62,4 +62,5 @@ export type LineDiscount = {
|
||||
export type LineDiscountAmount = {
|
||||
item: LineItem
|
||||
amount: number
|
||||
customAdjustmentsAmount: number
|
||||
}
|
||||
Reference in new issue
Block a user