Skip to content

Commit

Permalink
fix(core): Prevent negative total from compounded promotions
Browse files Browse the repository at this point in the history
Fixes #2385
  • Loading branch information
michaelbromley committed Sep 21, 2023
1 parent 0ddee96 commit 0740c87
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 5 deletions.
83 changes: 79 additions & 4 deletions packages/core/e2e/order-promotion.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1550,8 +1550,8 @@ describe('Promotions applied to Orders', () => {
>(APPLY_COUPON_CODE, { couponCode: TEST_COUPON_CODE });
orderResultGuard.assertSuccess(applyCouponCode);

expect(applyCouponCode!.totalWithTax).toBe(0);
expect(applyCouponCode!.couponCodes).toEqual([TEST_COUPON_CODE]);
expect(applyCouponCode.totalWithTax).toBe(0);
expect(applyCouponCode.couponCodes).toEqual([TEST_COUPON_CODE]);

await shopClient.query<SetCustomerForOrder.Mutation, SetCustomerForOrder.Variables>(
SET_CUSTOMER,
Expand All @@ -1565,8 +1565,8 @@ describe('Promotions applied to Orders', () => {
);

const { activeOrder } = await shopClient.query<GetActiveOrder.Query>(GET_ACTIVE_ORDER);
expect(activeOrder!.couponCodes).toEqual([TEST_COUPON_CODE]);
expect(applyCouponCode!.totalWithTax).toBe(0);
expect(activeOrder.couponCodes).toEqual([TEST_COUPON_CODE]);
expect(applyCouponCode.totalWithTax).toBe(0);
});
});

Expand Down Expand Up @@ -1755,6 +1755,81 @@ describe('Promotions applied to Orders', () => {
expect(applyCouponCode.totalWithTax).toBe(96);
});

// https://github.com/vendure-ecommerce/vendure/issues/2385
it('prevents negative line price', async () => {
await shopClient.asAnonymousUser();
const item1000 = getVariantBySlug('item-1000')!;
const couponCode1 = '100%_off';
const couponCode2 = '100%_off';
await createPromotion({
enabled: true,
name: '100% discount ',
couponCode: couponCode1,
conditions: [],
actions: [
{
code: productsPercentageDiscount.code,
arguments: [
{ name: 'discount', value: '100' },
{
name: 'productVariantIds',
value: `["${item1000.id}"]`,
},
],
},
],
});
await createPromotion({
enabled: true,
name: '20% discount ',
couponCode: couponCode2,
conditions: [],
actions: [
{
code: productsPercentageDiscount.code,
arguments: [
{ name: 'discount', value: '20' },
{
name: 'productVariantIds',
value: `["${item1000.id}"]`,
},
],
},
],
});

await shopClient.query<
CodegenShop.ApplyCouponCodeMutation,
CodegenShop.ApplyCouponCodeMutationVariables
>(APPLY_COUPON_CODE, { couponCode: couponCode1 });

await shopClient.query<
CodegenShop.AddItemToOrderMutation,
CodegenShop.AddItemToOrderMutationVariables
>(ADD_ITEM_TO_ORDER, {
productVariantId: item1000.id,
quantity: 1,
});

const { activeOrder: check1 } = await shopClient.query<CodegenShop.GetActiveOrderQuery>(
GET_ACTIVE_ORDER,
);

expect(check1!.lines[0].discountedUnitPriceWithTax).toBe(0);
expect(check1!.totalWithTax).toBe(0);

await shopClient.query<
CodegenShop.ApplyCouponCodeMutation,
CodegenShop.ApplyCouponCodeMutationVariables
>(APPLY_COUPON_CODE, { couponCode: couponCode2 });

const { activeOrder: check2 } = await shopClient.query<CodegenShop.GetActiveOrderQuery>(
GET_ACTIVE_ORDER,
);
expect(check2!.lines[0].discountedUnitPriceWithTax).toBe(0);
expect(check2!.totalWithTax).toBe(0);
});

async function getProducts() {
const result = await adminClient.query<Codegen.GetProductsWithVariantPricesQuery>(
GET_PRODUCTS_WITH_VARIANT_PRICES,
Expand Down
11 changes: 10 additions & 1 deletion packages/core/src/entity/order-line/order-line.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,16 @@ export class OrderLine extends VendureEntity implements HasCustomFields {
}

addAdjustment(adjustment: Adjustment) {
this.adjustments = this.adjustments.concat(adjustment);
// We should not allow adding adjustments which would
// result in a negative unit price
const maxDiscount = this.proratedLinePrice * -1;
const limitedAdjustment: Adjustment = {
...adjustment,
amount: Math.max(maxDiscount, adjustment.amount),
};
if (limitedAdjustment.amount !== 0) {
this.adjustments = this.adjustments.concat(limitedAdjustment);
}
}

/**
Expand Down

0 comments on commit 0740c87

Please sign in to comment.