fix(medusa): validate customer for group discount (#3797)

* fix: validate customer for group discount

* fix: remove logger

* fix: add generated desc

* fix: add an integration test case

* refactor: update error message

* fix: typo

* refactor: move condition

---------

Co-authored-by: fPolic <frane@medusajs.com>
This commit is contained in:
Frane Polić
2023-04-11 14:16:18 +02:00
committed by GitHub
parent 99cc4b0571
commit 78ff64e783
6 changed files with 87 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
"@medusajs/medusa": patch
---
fix(medusa); validate customer id when applying a customer group discount

View File

@@ -1083,6 +1083,63 @@ describe("/store/carts", () => {
expect(response.status).toEqual(200)
})
it("throws if no customer is associated with the cart while applying a customer groups discount", async () => {
const api = useApi()
await simpleCustomerGroupFactory(dbConnection, {
id: "customer-group-2",
name: "Loyal",
})
await simpleCartFactory(
dbConnection,
{
id: "test-customer-discount",
region: {
id: "test-region",
name: "Test region",
tax_rate: 12,
},
line_items: [
{
variant_id: "test-variant",
unit_price: 100,
},
],
},
100
)
await simpleDiscountFactory(dbConnection, {
id: "test-discount",
code: "TEST",
regions: ["test-region"],
rule: {
type: "percentage",
value: "10",
allocation: "total",
conditions: [
{
type: "customer_groups",
operator: "in",
customer_groups: ["customer-group-2"],
},
],
},
})
try {
await api.post("/store/carts/test-customer-discount", {
discounts: [{ code: "TEST" }],
})
} catch (error) {
expect(error.response.status).toEqual(400)
expect(error.response.data.message).toEqual(
"Discount TEST is only valid for specific customer"
)
}
})
it("successfully removes adjustments upon update without discounts", async () => {
const discountData = {
code: "MEDUSA185DKK",

View File

@@ -44,7 +44,7 @@ export interface StorePostCartsCartReq {
*/
discounts?: Array<{
/**
* The code that a Discount is identifed by.
* The code that a Discount is identified by.
*/
code: string
}>

View File

@@ -168,7 +168,7 @@ class Discount {
* - code
* properties:
* code:
* description: "The code that a Discount is identifed by."
* description: "The code that a Discount is identified by."
* type: string
* customer_id:
* description: "The ID of the Customer to associate the Cart with."

View File

@@ -1443,7 +1443,9 @@ class CartService extends TransactionBaseService {
async (transactionManager: EntityManager) => {
const discounts = await this.discountService_
.withTransaction(transactionManager)
.listByCodes(discountCodes, { relations: ["rule", "regions"] })
.listByCodes(discountCodes, {
relations: ["rule", "rule.conditions", "regions"],
})
await this.discountService_
.withTransaction(transactionManager)

View File

@@ -16,7 +16,13 @@ import {
} from "."
import { TransactionBaseService } from "../interfaces"
import TaxInclusivePricingFeatureFlag from "../loaders/feature-flags/tax-inclusive-pricing"
import { Cart, Discount, LineItem, Region } from "../models"
import {
Cart,
Discount,
DiscountConditionType,
LineItem,
Region,
} from "../models"
import {
AllocationType as DiscountAllocation,
DiscountRule,
@@ -705,6 +711,13 @@ class DiscountService extends TransactionBaseService {
)
}
if (!cart.customer_id && this.hasCustomersGroupCondition(disc)) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
`Discount ${disc.code} is only valid for specific customer`
)
}
const isValidForRegion = await this.isValidForRegion(
disc,
cart.region_id
@@ -734,6 +747,12 @@ class DiscountService extends TransactionBaseService {
})
}
hasCustomersGroupCondition(discount: Discount): boolean {
return discount.rule.conditions.some(
(cond) => cond.type === DiscountConditionType.CUSTOMER_GROUPS
)
}
hasReachedLimit(discount: Discount): boolean {
const count = discount.usage_count || 0
const limit = discount.usage_limit