Adds DiscountService and TotalsService (#26)
This commit is contained in:
1 parent
f6d5180e5f
commit
aff1ec3390
15 files changed
+1404
-2
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
import { discounts } from "./discount"
|
||||
|
||||
export const carts = {
|
||||
emptyCart: {
|
||||
@@ -255,6 +256,59 @@ export const carts = {
|
||||
discounts: [],
|
||||
customer_id: "",
|
||||
},
|
||||
discountCartWithExisting: {
|
||||
_id: IdMap.getId("discount-cart-with-existing"),
|
||||
discounts: [discounts.item10Percent],
|
||||
region_id: IdMap.getId("region-france"),
|
||||
items: [
|
||||
{
|
||||
_id: IdMap.getId("line"),
|
||||
title: "merge line",
|
||||
description: "This is a new line",
|
||||
thumbnail: "test-img-yeah.com/thumb",
|
||||
content: [
|
||||
{
|
||||
unit_price: 8,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-8-us-10"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
{
|
||||
unit_price: 10,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-10-us-12"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
quantity: 10,
|
||||
},
|
||||
{
|
||||
_id: IdMap.getId("existingLine"),
|
||||
title: "merge line",
|
||||
description: "This is a new line",
|
||||
thumbnail: "test-img-yeah.com/thumb",
|
||||
content: {
|
||||
unit_price: 10,
|
||||
variant: {
|
||||
_id: IdMap.getId("eur-10-us-12"),
|
||||
},
|
||||
product: {
|
||||
_id: IdMap.getId("product"),
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
quantity: 10,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
export const CartModelMock = {
|
||||
@@ -285,6 +339,9 @@ export const CartModelMock = {
|
||||
if (query._id === IdMap.getId("complete-cart")) {
|
||||
return Promise.resolve(carts.completeCart)
|
||||
}
|
||||
if (query._id === IdMap.getId("discount-cart-with-existing")) {
|
||||
return Promise.resolve(carts.discountCartWithExisting)
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
import { IdMap } from "medusa-test-utils"
|
||||
|
||||
export const discounts = {
|
||||
total10Percent: {
|
||||
_id: IdMap.getId("total10"),
|
||||
code: "10%OFF",
|
||||
discount_rule: {
|
||||
type: "percentage",
|
||||
allocation: "total",
|
||||
value: 10,
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
item10Percent: {
|
||||
_id: IdMap.getId("item10Percent"),
|
||||
code: "MEDUSA",
|
||||
discount_rule: {
|
||||
type: "percentage",
|
||||
allocation: "item",
|
||||
value: 10,
|
||||
valid_for: [IdMap.getId("eur-8-us-10"), IdMap.getId("eur-10-us-12")],
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
total10Fixed: {
|
||||
_id: IdMap.getId("total10Fixed"),
|
||||
code: "MEDUSA",
|
||||
discount_rule: {
|
||||
type: "fixed",
|
||||
allocation: "total",
|
||||
value: 10,
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
item9Fixed: {
|
||||
_id: IdMap.getId("item9Fixed"),
|
||||
code: "MEDUSA",
|
||||
discount_rule: {
|
||||
type: "fixed",
|
||||
allocation: "item",
|
||||
value: 9,
|
||||
valid_for: [IdMap.getId("eur-8-us-10"), IdMap.getId("eur-10-us-12")],
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
item2Fixed: {
|
||||
_id: IdMap.getId("item2Fixed"),
|
||||
code: "MEDUSA",
|
||||
discount_rule: {
|
||||
type: "fixed",
|
||||
allocation: "item",
|
||||
value: 2,
|
||||
valid_for: [IdMap.getId("eur-8-us-10"), IdMap.getId("eur-10-us-12")],
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
item10FixedNoVariants: {
|
||||
_id: IdMap.getId("item10FixedNoVariants"),
|
||||
code: "MEDUSA",
|
||||
discount_rule: {
|
||||
type: "fixed",
|
||||
allocation: "item",
|
||||
value: 10,
|
||||
valid_for: [],
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
expiredDiscount: {
|
||||
_id: IdMap.getId("expired"),
|
||||
code: "MEDUSA",
|
||||
ends_at: new Date("December 17, 1995 03:24:00"),
|
||||
discount_rule: {
|
||||
type: "fixed",
|
||||
allocation: "item",
|
||||
value: 10,
|
||||
valid_for: [],
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
freeShipping: {
|
||||
_id: IdMap.getId("freeshipping"),
|
||||
code: "FREESHIPPING",
|
||||
discount_rule: {
|
||||
type: "free_shipping",
|
||||
allocation: "total",
|
||||
value: 10,
|
||||
valid_for: [],
|
||||
},
|
||||
regions: [IdMap.getId("region-france")],
|
||||
},
|
||||
USDiscount: {
|
||||
_id: IdMap.getId("us-discount"),
|
||||
code: "US10",
|
||||
discount_rule: {
|
||||
type: "free_shipping",
|
||||
allocation: "total",
|
||||
value: 10,
|
||||
valid_for: [],
|
||||
},
|
||||
regions: [IdMap.getId("us")],
|
||||
},
|
||||
alreadyExists: {
|
||||
code: "ALREADYEXISTS",
|
||||
discount_rule: {
|
||||
type: "percentage",
|
||||
allocation: "total",
|
||||
value: 20,
|
||||
},
|
||||
regions: [IdMap.getId("fr-cart")],
|
||||
},
|
||||
}
|
||||
|
||||
export const DiscountModelMock = {
|
||||
create: jest.fn().mockReturnValue(Promise.resolve()),
|
||||
updateOne: jest.fn().mockImplementation((query, update) => {
|
||||
return Promise.resolve()
|
||||
}),
|
||||
deleteOne: jest.fn().mockReturnValue(Promise.resolve()),
|
||||
findOne: jest.fn().mockImplementation(query => {
|
||||
if (query._id === IdMap.getId("total10")) {
|
||||
return Promise.resolve(discounts.total10Percent)
|
||||
}
|
||||
if (query._id === IdMap.getId("item10Percent")) {
|
||||
return Promise.resolve(discounts.item10Percent)
|
||||
}
|
||||
if (query._id === IdMap.getId("total10Fixed")) {
|
||||
return Promise.resolve(discounts.total10Fixed)
|
||||
}
|
||||
if (query._id === IdMap.getId("item2Fixed")) {
|
||||
return Promise.resolve(discounts.item2Fixed)
|
||||
}
|
||||
if (query._id === IdMap.getId("item10FixedNoVariants")) {
|
||||
return Promise.resolve(discounts.item10FixedNoVariants)
|
||||
}
|
||||
if (query._id === IdMap.getId("expired")) {
|
||||
return Promise.resolve(discounts.expiredDiscount)
|
||||
}
|
||||
if (query.code === "10%OFF") {
|
||||
return Promise.resolve(discounts.total10Percent)
|
||||
}
|
||||
if (query.code === "aLrEaDyExIsts") {
|
||||
return Promise.resolve(discounts.alreadyExists)
|
||||
}
|
||||
return Promise.resolve(undefined)
|
||||
}),
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import LineItemSchema from "./schemas/line-item"
|
||||
import PaymentMethodSchema from "./schemas/payment-method"
|
||||
import ShippingMethodSchema from "./schemas/shipping-method"
|
||||
import AddressSchema from "./schemas/address"
|
||||
import DiscountModel from "./discount"
|
||||
|
||||
class CartModel extends BaseModel {
|
||||
static modelName = "Cart"
|
||||
@@ -18,7 +19,7 @@ class CartModel extends BaseModel {
|
||||
shipping_address: { type: AddressSchema, default: {} },
|
||||
items: { type: [LineItemSchema], default: [] },
|
||||
region_id: { type: String, required: true },
|
||||
discounts: { type: [String], default: [] },
|
||||
discounts: { type: [DiscountModel.schema], default: [] },
|
||||
customer_id: { type: String, default: "" },
|
||||
payment_sessions: { type: [PaymentMethodSchema], default: [] },
|
||||
shipping_options: { type: [ShippingMethodSchema], default: [] },
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import { BaseModel } from "medusa-interfaces"
|
||||
import DiscountRule from "./schemas/discount-rule"
|
||||
|
||||
class DiscountModel extends BaseModel {
|
||||
static modelName = "Discount"
|
||||
|
||||
static schema = {
|
||||
code: { type: String, required: true, unique: true },
|
||||
discount_rule: { type: DiscountRule, required: true },
|
||||
usage_count: { type: Number, default: 0 },
|
||||
disabled: { type: Boolean, default: false },
|
||||
starts_at: { type: Date },
|
||||
ends_at: { type: Date },
|
||||
regions: { type: [String], default: [] },
|
||||
metadata: { type: mongoose.Schema.Types.Mixed, default: {} },
|
||||
}
|
||||
}
|
||||
|
||||
export default DiscountModel
|
||||
@@ -0,0 +1,28 @@
|
||||
import mongoose from "mongoose"
|
||||
|
||||
export default new mongoose.Schema({
|
||||
description: { type: String },
|
||||
// Fixed, percentage or free shipping is allowed as type.
|
||||
// The fixed discount type can be used as normal coupon code, giftcards,
|
||||
// store credits and possibly more.
|
||||
// The percentage discount type can be used as normal coupon code, giftcards
|
||||
// and possibly more.
|
||||
// The free shipping discount type is used only to give free shipping.
|
||||
type: { type: String, required: true }, // Fixed, percent, free shipping
|
||||
// The value is simply the amount of discount a customer or user will have.
|
||||
// This depends on the type above, since percentage can not be above 100.
|
||||
value: { type: Number, required: true },
|
||||
// This is either total, meaning that the discount will be applied to the
|
||||
// total price of the cart
|
||||
// or item, meaning that the discount can be applied to the product variants
|
||||
// in the valid_for array. Lastly the allocation is completely ignored if
|
||||
// discount type is free shipping.
|
||||
allocation: { type: String, required: true },
|
||||
// Id's of product variants. Depends on allocation.
|
||||
// If total is set, then the valid_for will not be used for anything,
|
||||
// since the discount will work for the cart total. Else if item allocation
|
||||
// is chosen, then we will go through the cart and apply the coupon code to
|
||||
// all the valid product variants.
|
||||
valid_for: { type: [String], default: [] },
|
||||
usage_limit: { type: Number },
|
||||
})
|
||||
Reference in new issue
Block a user