feat(medusa): Preserve custom adjustments when refreshing adjustments (#3085)
This commit is contained in:
1 parent
d0adaf57ed
commit
5b63533c77
10 files changed
+291
-33
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(medusa): preserve custom adjustments when refreshing adjustments
|
||||||
@@ -2699,6 +2699,154 @@ describe("/admin/order-edits", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("Preserve custom adjustments on items change", () => {
|
||||||
|
let product
|
||||||
|
let product2
|
||||||
|
const orderId = IdMap.getId("order-1")
|
||||||
|
const prodId1 = IdMap.getId("product-1")
|
||||||
|
const prodId2 = IdMap.getId("product-2")
|
||||||
|
const lineItemId1 = IdMap.getId("line-item-1")
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await adminSeeder(dbConnection)
|
||||||
|
|
||||||
|
product = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId1,
|
||||||
|
})
|
||||||
|
|
||||||
|
product2 = await simpleProductFactory(dbConnection, {
|
||||||
|
id: prodId2,
|
||||||
|
})
|
||||||
|
|
||||||
|
await simpleOrderFactory(dbConnection, {
|
||||||
|
id: orderId,
|
||||||
|
email: "test@testson.com",
|
||||||
|
region: {
|
||||||
|
id: "test-region",
|
||||||
|
name: "Test region",
|
||||||
|
tax_rate: 12.5,
|
||||||
|
},
|
||||||
|
tax_rate: null,
|
||||||
|
line_items: [
|
||||||
|
{
|
||||||
|
adjustments: [
|
||||||
|
{
|
||||||
|
item_id: lineItemId1,
|
||||||
|
amount: 200,
|
||||||
|
description: "custom adjustment that should be persisted",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
id: lineItemId1,
|
||||||
|
variant_id: product.variants[0].id,
|
||||||
|
quantity: 1,
|
||||||
|
fulfilled_quantity: 1,
|
||||||
|
shipped_quantity: 1,
|
||||||
|
unit_price: 1000,
|
||||||
|
tax_lines: [
|
||||||
|
{
|
||||||
|
item_id: lineItemId1,
|
||||||
|
rate: 12.5,
|
||||||
|
code: "default",
|
||||||
|
name: "default",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
const db = useDb()
|
||||||
|
return await db.teardown()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("preserve custom line item on update item change", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: { order_edit },
|
||||||
|
} = await api.post(
|
||||||
|
`/admin/order-edits/`,
|
||||||
|
{
|
||||||
|
order_id: orderId,
|
||||||
|
internal_note: "This is an internal note",
|
||||||
|
},
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
const orderEditId = order_edit.id
|
||||||
|
const updateItemId = order_edit.items.find(
|
||||||
|
(item) => item.original_item_id === lineItemId1
|
||||||
|
).id
|
||||||
|
|
||||||
|
const response = await api.post(
|
||||||
|
`/admin/order-edits/${orderEditId}/items/${updateItemId}`,
|
||||||
|
{ quantity: 2 },
|
||||||
|
adminHeaders
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.order_edit.changes).toHaveLength(1)
|
||||||
|
expect(response.data.order_edit).toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
id: orderEditId,
|
||||||
|
changes: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
created_at: expect.any(String),
|
||||||
|
updated_at: expect.any(String),
|
||||||
|
deleted_at: null,
|
||||||
|
type: "item_update",
|
||||||
|
order_edit_id: orderEditId,
|
||||||
|
original_line_item_id: lineItemId1,
|
||||||
|
line_item_id: expect.any(String),
|
||||||
|
line_item: expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
}),
|
||||||
|
original_line_item: expect.objectContaining({
|
||||||
|
id: lineItemId1,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
status: "created",
|
||||||
|
order_id: orderId,
|
||||||
|
internal_note: "This is an internal note",
|
||||||
|
created_by: "admin_user",
|
||||||
|
items: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
id: expect.any(String),
|
||||||
|
original_item_id: lineItemId1,
|
||||||
|
order_edit_id: orderEditId,
|
||||||
|
quantity: 2,
|
||||||
|
adjustments: [
|
||||||
|
expect.objectContaining({
|
||||||
|
amount: 200,
|
||||||
|
description: "custom adjustment that should be persisted",
|
||||||
|
discount_id: null,
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
tax_lines: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
rate: 12.5,
|
||||||
|
name: "default",
|
||||||
|
code: "default",
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
// 2 items with unit price 1000 and a custom line item adjustment of 200
|
||||||
|
gift_card_total: 0,
|
||||||
|
gift_card_tax_total: 0,
|
||||||
|
shipping_total: 0,
|
||||||
|
discount_total: 200,
|
||||||
|
subtotal: 2 * 1000,
|
||||||
|
tax_total: (2000 - 200) * 0.125,
|
||||||
|
total: 1800 * 0.125 + 1800,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("DELETE /admin/order-edits/:id/items/:item_id", () => {
|
describe("DELETE /admin/order-edits/:id/items/:item_id", () => {
|
||||||
let product
|
let product
|
||||||
let product2
|
let product2
|
||||||
|
|||||||
@@ -207,4 +207,81 @@ describe("Line Item Adjustments", () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("When refreshing adjustments make sure that only adjustments associated with a Medusa Discount are deleted", () => {
|
||||||
|
let cart
|
||||||
|
let discount
|
||||||
|
const lineItemId = "line-test"
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await cartSeeder(dbConnection)
|
||||||
|
|
||||||
|
discount = await simpleDiscountFactory(dbConnection, {
|
||||||
|
code: "MEDUSATEST",
|
||||||
|
id: "discount-test",
|
||||||
|
rule: {
|
||||||
|
value: 100,
|
||||||
|
type: "fixed",
|
||||||
|
allocation: "total",
|
||||||
|
},
|
||||||
|
regions: ["test-region"],
|
||||||
|
})
|
||||||
|
|
||||||
|
cart = await simpleCartFactory(
|
||||||
|
dbConnection,
|
||||||
|
{
|
||||||
|
customer: "test-customer",
|
||||||
|
id: "cart-test",
|
||||||
|
line_items: [
|
||||||
|
{
|
||||||
|
id: lineItemId,
|
||||||
|
variant_id: "test-variant",
|
||||||
|
cart_id: "cart-test",
|
||||||
|
unit_price: 1000,
|
||||||
|
quantity: 1,
|
||||||
|
adjustments: [
|
||||||
|
{
|
||||||
|
amount: 10,
|
||||||
|
discount_id: discount.id,
|
||||||
|
description: "discount",
|
||||||
|
item_id: lineItemId,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// this one shouldn't be deleted because it's
|
||||||
|
// not associated with a Medusa Discount, i.e.
|
||||||
|
// it's created by a third party system, for example,
|
||||||
|
// a custom promotions engine
|
||||||
|
amount: 20,
|
||||||
|
description: "custom adjustment without discount",
|
||||||
|
item_id: lineItemId,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
region: "test-region",
|
||||||
|
},
|
||||||
|
100
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await doAfterEach()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("Delete only adjustments of the removed discount and keep 'custom' adjustments", async () => {
|
||||||
|
const api = useApi()
|
||||||
|
|
||||||
|
const response = await api.delete(
|
||||||
|
`/store/carts/${cart.id}/discounts/${discount.code}`
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(response.status).toEqual(200)
|
||||||
|
expect(response.data.cart.items[0].adjustments.length).toEqual(1)
|
||||||
|
expect(response.data.cart.items[0].adjustments[0]).toMatchObject({
|
||||||
|
amount: 20,
|
||||||
|
description: "custom adjustment without discount",
|
||||||
|
item_id: lineItemId,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
@@ -165,7 +165,9 @@ describe("/admin/orders", () => {
|
|||||||
* shipping method will have 12.5 rate 1000 * 1.125 = 1125
|
* shipping method will have 12.5 rate 1000 * 1.125 = 1125
|
||||||
*/
|
*/
|
||||||
expect(response.data.order.returns[0].refund_amount).toEqual(75)
|
expect(response.data.order.returns[0].refund_amount).toEqual(75)
|
||||||
expect(response.data.order.returns[0].shipping_method.tax_lines).toHaveLength(1)
|
expect(
|
||||||
|
response.data.order.returns[0].shipping_method.tax_lines
|
||||||
|
).toHaveLength(1)
|
||||||
expect(response.data.order.returns[0].shipping_method.tax_lines).toEqual(
|
expect(response.data.order.returns[0].shipping_method.tax_lines).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@@ -358,14 +360,16 @@ const createReturnableOrder = async (dbConnection, options) => {
|
|||||||
fulfilled_quantity: options.shipped ? 2 : undefined,
|
fulfilled_quantity: options.shipped ? 2 : undefined,
|
||||||
shipped_quantity: options.shipped ? 2 : undefined,
|
shipped_quantity: options.shipped ? 2 : undefined,
|
||||||
unit_price: 1000,
|
unit_price: 1000,
|
||||||
adjustments: [
|
adjustments: options.discount
|
||||||
|
? [
|
||||||
{
|
{
|
||||||
amount: 200,
|
amount: 200,
|
||||||
discount_code: "TESTCODE",
|
discount_code: "TESTCODE",
|
||||||
description: "discount",
|
description: "discount",
|
||||||
item_id: "test-item",
|
item_id: "test-item",
|
||||||
},
|
},
|
||||||
],
|
]
|
||||||
|
: [],
|
||||||
tax_lines: [
|
tax_lines: [
|
||||||
{
|
{
|
||||||
name: "default",
|
name: "default",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { ShippingOptionServiceMock } from "../__mocks__/shipping-option"
|
|||||||
import { CustomerServiceMock } from "../__mocks__/customer"
|
import { CustomerServiceMock } from "../__mocks__/customer"
|
||||||
import TaxCalculationStrategy from "../../strategies/tax-calculation"
|
import TaxCalculationStrategy from "../../strategies/tax-calculation"
|
||||||
import SystemTaxService from "../system-tax"
|
import SystemTaxService from "../system-tax"
|
||||||
|
import { IsNull, Not } from "typeorm"
|
||||||
|
|
||||||
const eventBusService = {
|
const eventBusService = {
|
||||||
emit: jest.fn(),
|
emit: jest.fn(),
|
||||||
@@ -515,6 +516,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: [IdMap.getId("merger")],
|
item_id: [IdMap.getId("merger")],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -745,6 +747,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: [IdMap.getId("itemToRemove")],
|
item_id: [IdMap.getId("itemToRemove")],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -786,6 +789,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: [IdMap.getId("itemToRemove")],
|
item_id: [IdMap.getId("itemToRemove")],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -965,6 +969,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: [IdMap.getId("existingUpdate")],
|
item_id: [IdMap.getId("existingUpdate")],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -2259,6 +2264,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: ["li1", "li2"],
|
item_id: ["li1", "li2"],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -2309,6 +2315,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: ["li1", "li2"],
|
item_id: ["li1", "li2"],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -2368,6 +2375,7 @@ describe("CartService", () => {
|
|||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledTimes(1)
|
||||||
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
expect(LineItemAdjustmentServiceMock.delete).toHaveBeenCalledWith({
|
||||||
item_id: ["li1", "li2"],
|
item_id: ["li1", "li2"],
|
||||||
|
discount_id: expect.objectContaining(Not(IsNull())),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { isEmpty, isEqual } from "lodash"
|
import { isEmpty, isEqual } from "lodash"
|
||||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
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 { IPriceSelectionStrategy, TransactionBaseService } from "../interfaces"
|
||||||
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
|
import SalesChannelFeatureFlag from "../loaders/feature-flags/sales-channels"
|
||||||
import {
|
import {
|
||||||
@@ -2604,6 +2604,7 @@ class CartService extends TransactionBaseService {
|
|||||||
.withTransaction(transactionManager)
|
.withTransaction(transactionManager)
|
||||||
.delete({
|
.delete({
|
||||||
item_id: nonReturnLineIDs,
|
item_id: nonReturnLineIDs,
|
||||||
|
discount_id: Not(IsNull()),
|
||||||
})
|
})
|
||||||
|
|
||||||
// potentially create/update line item adjustments
|
// potentially create/update line item adjustments
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
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 { Cart, DiscountRuleType, LineItem, LineItemAdjustment } from "../models"
|
||||||
import { LineItemAdjustmentRepository } from "../repositories/line-item-adjustment"
|
import { LineItemAdjustmentRepository } from "../repositories/line-item-adjustment"
|
||||||
@@ -153,7 +153,12 @@ class LineItemAdjustmentService extends TransactionBaseService {
|
|||||||
* @return the result of the delete operation
|
* @return the result of the delete operation
|
||||||
*/
|
*/
|
||||||
async delete(
|
async delete(
|
||||||
selectorOrIds: string | string[] | FilterableLineItemAdjustmentProps
|
selectorOrIds:
|
||||||
|
| string
|
||||||
|
| string[]
|
||||||
|
| (FilterableLineItemAdjustmentProps & {
|
||||||
|
discount_id?: FindOperator<string | null>
|
||||||
|
})
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.atomicPhase_(async (manager) => {
|
return this.atomicPhase_(async (manager) => {
|
||||||
const lineItemAdjustmentRepo: LineItemAdjustmentRepository =
|
const lineItemAdjustmentRepo: LineItemAdjustmentRepository =
|
||||||
|
|||||||
@@ -373,7 +373,9 @@ export default class OrderEditService extends TransactionBaseService {
|
|||||||
quantity: data.quantity,
|
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 manager = this.transactionManager_ ?? this.manager_
|
||||||
|
|
||||||
const lineItemAdjustmentServiceTx =
|
const lineItemAdjustmentServiceTx =
|
||||||
@@ -461,7 +466,13 @@ export default class OrderEditService extends TransactionBaseService {
|
|||||||
orderEdit.items.forEach((item) => {
|
orderEdit.items.forEach((item) => {
|
||||||
if (item.adjustments?.length) {
|
if (item.adjustments?.length) {
|
||||||
item.adjustments.forEach((adjustment) => {
|
item.adjustments.forEach((adjustment) => {
|
||||||
|
const preserveAdjustment = config.preserveCustomAdjustments
|
||||||
|
? !!adjustment.discount_id
|
||||||
|
: true
|
||||||
|
|
||||||
|
if (preserveAdjustment) {
|
||||||
clonedItemAdjustmentIds.push(adjustment.id)
|
clonedItemAdjustmentIds.push(adjustment.id)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -447,26 +447,28 @@ class TotalsService extends TransactionBaseService {
|
|||||||
const allocationMap: LineAllocationsMap = {}
|
const allocationMap: LineAllocationsMap = {}
|
||||||
|
|
||||||
if (!options.exclude_discounts) {
|
if (!options.exclude_discounts) {
|
||||||
let lineDiscounts: LineDiscountAmount[] = []
|
|
||||||
|
|
||||||
const discount = orderOrCart.discounts?.find(
|
const discount = orderOrCart.discounts?.find(
|
||||||
({ rule }) => rule.type !== DiscountRuleType.FREE_SHIPPING
|
({ 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) {
|
for (const ld of lineDiscounts) {
|
||||||
|
const adjustmentAmount = ld.amount + ld.customAdjustmentsAmount
|
||||||
|
|
||||||
if (allocationMap[ld.item.id]) {
|
if (allocationMap[ld.item.id]) {
|
||||||
allocationMap[ld.item.id].discount = {
|
allocationMap[ld.item.id].discount = {
|
||||||
amount: ld.amount,
|
amount: adjustmentAmount,
|
||||||
unit_amount: Math.round(ld.amount / ld.item.quantity),
|
unit_amount: Math.round(adjustmentAmount / ld.item.quantity),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allocationMap[ld.item.id] = {
|
allocationMap[ld.item.id] = {
|
||||||
discount: {
|
discount: {
|
||||||
amount: ld.amount,
|
amount: adjustmentAmount,
|
||||||
unit_amount: Math.round(ld.amount / ld.item.quantity),
|
unit_amount: Math.round(adjustmentAmount / ld.item.quantity),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -717,7 +719,7 @@ class TotalsService extends TransactionBaseService {
|
|||||||
swaps?: Swap[]
|
swaps?: Swap[]
|
||||||
claims?: ClaimOrder[]
|
claims?: ClaimOrder[]
|
||||||
},
|
},
|
||||||
discount: Discount
|
discount?: Discount
|
||||||
): LineDiscountAmount[] {
|
): LineDiscountAmount[] {
|
||||||
let merged: LineItem[] = [...(cartOrOrder.items ?? [])]
|
let merged: LineItem[] = [...(cartOrOrder.items ?? [])]
|
||||||
|
|
||||||
@@ -736,18 +738,24 @@ class TotalsService extends TransactionBaseService {
|
|||||||
|
|
||||||
return merged.map((item) => {
|
return merged.map((item) => {
|
||||||
const adjustments = item?.adjustments || []
|
const adjustments = item?.adjustments || []
|
||||||
const discountAdjustments = adjustments.filter(
|
const discountAdjustments = discount
|
||||||
|
? adjustments.filter(
|
||||||
(adjustment) => adjustment.discount_id === discount.id
|
(adjustment) => adjustment.discount_id === discount.id
|
||||||
)
|
)
|
||||||
|
: []
|
||||||
|
|
||||||
|
const customAdjustments = adjustments.filter(
|
||||||
|
(adjustment) => adjustment.discount_id === null
|
||||||
|
)
|
||||||
|
|
||||||
|
const sumAdjustments = (total, adjustment) => total + adjustment.amount
|
||||||
|
|
||||||
return {
|
return {
|
||||||
item,
|
item,
|
||||||
amount: item.allow_discounts
|
amount: item.allow_discounts
|
||||||
? discountAdjustments.reduce(
|
? discountAdjustments.reduce(sumAdjustments, 0)
|
||||||
(total, adjustment) => total + adjustment.amount,
|
|
||||||
0
|
|
||||||
)
|
|
||||||
: 0,
|
: 0,
|
||||||
|
customAdjustmentsAmount: customAdjustments.reduce(sumAdjustments, 0),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -994,16 +1002,6 @@ class TotalsService extends TransactionBaseService {
|
|||||||
excludeNonDiscounts: true,
|
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)
|
const discountTotal = this.getLineItemAdjustmentsTotal(cartOrOrder)
|
||||||
|
|
||||||
if (subtotal < 0) {
|
if (subtotal < 0) {
|
||||||
|
|||||||
@@ -62,4 +62,5 @@ export type LineDiscount = {
|
|||||||
export type LineDiscountAmount = {
|
export type LineDiscountAmount = {
|
||||||
item: LineItem
|
item: LineItem
|
||||||
amount: number
|
amount: number
|
||||||
|
customAdjustmentsAmount: number
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user