feat: new tax api (#979)
* feat: add tax calculation strategy (#885) * feat: add tax calculation strategy * fix: adds strategy loader * fix: eslint ignore * chore: cleanup * fix: allow plugin overwrites * fix: allow plugin overwrites * fix: fake region * Update packages/medusa/src/loaders/strategies.ts Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com> * feat: adds tax related db entities + tax provider (#896) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: pr comments * fix: unit test * feat: totals service to ts (#911) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * feat: totals service to ts * fix: remove totals.js * fix: add shipping methods * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: tests * fix: tests * fix: unit test * fix: adds TotalsServiceProps * feat: adds integration tests for automatic tax calculation + shipping tax rates (#945) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * feat: totals service to ts * fix: remove totals.js * fix: add shipping methods * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: tests * fix: tests * fix: unit test * fix: integration test helpers * fix: adds factories + tests automatic tax rates * fix: remove verbose * fix: adds TotalsServiceProps * fix: add shipping tax lines * fix: add migration for shipping taxes * fix: integration tests for shipping taxes * fix: integration tests for shipping taxes * fix: jsdoc types * Feat/manual taxes (#950) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * feat: totals service to ts * fix: remove totals.js * fix: add shipping methods * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: tests * fix: tests * fix: unit test * fix: integration test helpers * fix: adds factories + tests automatic tax rates * fix: remove verbose * fix: adds TotalsServiceProps * fix: add shipping tax lines * fix: add migration for shipping taxes * fix: integration tests for shipping taxes * fix: integration tests for shipping taxes * fix: add integration tests for manual taxes * fix: cart service - cleanup jsdoc * feat: add /carts/id/taxes to manually calculate taxes * feat: add integration tests for order tax calculations * fix: unit tests * fix: merge * fix: rm verbose * fix: unit tests * fix: object -> cartOrOrder * fix: rounding * Feat/complete order w tax lines (#951) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * feat: totals service to ts * fix: remove totals.js * fix: add shipping methods * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: tests * fix: tests * fix: unit test * fix: integration test helpers * fix: adds factories + tests automatic tax rates * fix: remove verbose * fix: adds TotalsServiceProps * fix: add shipping tax lines * fix: add migration for shipping taxes * fix: integration tests for shipping taxes * fix: integration tests for shipping taxes * fix: add integration tests for manual taxes * fix: cart service - cleanup jsdoc * feat: add /carts/id/taxes to manually calculate taxes * feat: add integration tests for order tax calculations * feat: adds cart completion strategy + create order w. tax lines * fix: unit tests * fix: merge * fix: rm verbose * fix: unit tests * fix: unit tests * fix: unit tests * fix: ensure calculation for list orders * fix: unit tests * fix: integration tests * fix: adds cart order type gaurds * Docs/tax api (#954) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * feat: totals service to ts * fix: remove totals.js * fix: add shipping methods * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: tests * fix: tests * fix: unit test * fix: integration test helpers * fix: adds factories + tests automatic tax rates * fix: remove verbose * fix: adds TotalsServiceProps * fix: add shipping tax lines * fix: add migration for shipping taxes * fix: integration tests for shipping taxes * fix: integration tests for shipping taxes * fix: add integration tests for manual taxes * fix: cart service - cleanup jsdoc * feat: add /carts/id/taxes to manually calculate taxes * feat: add integration tests for order tax calculations * feat: adds cart completion strategy + create order w. tax lines * fix: unit tests * fix: merge * fix: rm verbose * fix: unit tests * fix: unit tests * fix: unit tests * fix: ensure calculation for list orders * fix: unit tests * fix: integration tests * docs: documents tax related methods and types * fix: require either item_id or shipping_method_id * feat: product type tax rate (#969) * feat: adds tax related db entities + tax provider * fix: add tax provider tests * fix: add tax service unit tests * fix: tests + migrations * feat: totals service to ts * fix: remove totals.js * fix: add shipping methods * fix: add inherited tax lines * chore: rm tax-line repo * fix: test * fix: tests * fix: tests * fix: unit test * fix: integration test helpers * fix: adds factories + tests automatic tax rates * fix: remove verbose * fix: adds TotalsServiceProps * fix: add shipping tax lines * fix: add migration for shipping taxes * fix: integration tests for shipping taxes * fix: integration tests for shipping taxes * fix: add integration tests for manual taxes * fix: cart service - cleanup jsdoc * feat: add /carts/id/taxes to manually calculate taxes * feat: add integration tests for order tax calculations * feat: adds cart completion strategy + create order w. tax lines * fix: unit tests * fix: merge * fix: rm verbose * fix: unit tests * fix: unit tests * fix: unit tests * fix: ensure calculation for list orders * fix: unit tests * fix: integration tests * docs: documents tax related methods and types * fix: require either item_id or shipping_method_id * feat: adds returns tests for new tax system * feat: adds return lines + integration tests for swaps * feat: return integration tests * feat: adds product type tax rates * feat: add tax management endpoints * fix: create single migration * fix: adds tax rates to js client * fix: strats * Fix/plugin tests (#998) * plugin testing setup * fix: test sendgrid plugin * fix: test sendgrid plugin * chore: clean * chore: clean * fix: clean up tests * fix: remove dirty import * fix: sendgrid + brightpearl * fix: plugin integration tests * fix: klarna * fix: shipping method tax * fix: remove taxrates * fix: unit tests * fix: integration * fix: integration * fix: plugins tests * fix: ignore plugins * fix: tests * fix: taxes (#1017) * fix: taxes * fix: taxes * fix: faulty ref * fix: create tax-lines with claim items * fix: snapshot tax-liens * fix: allows integration test teardown to force deleting tables * fix: tests * fix: merge * fix: adds tax-rates to client * fix: adds tax-rates to medusa-react * fix: tests * fix: tests * fix: add product types * fix: adds tax provider endpoint + cascaded deletes on tax rate relations * fix: move errors to service layer * fix: cleanup api * fix: unit tests * fix: error handler in base-service * fix: Add order region to swap on createFulfillment (#1110) Co-authored-by: Oliver Windall Juhl <59018053+olivermrbl@users.noreply.github.com>
This commit is contained in:
committed by
olivermrbl
parent
d80eaa172d
commit
47588e7a8d
13
integration-tests/plugins/factories/index.ts
Normal file
13
integration-tests/plugins/factories/index.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export * from "./simple-order-factory"
|
||||
export * from "./simple-cart-factory"
|
||||
export * from "./simple-region-factory"
|
||||
export * from "./simple-line-item-factory"
|
||||
export * from "./simple-product-factory"
|
||||
export * from "./simple-product-variant-factory"
|
||||
export * from "./simple-product-tax-rate-factory"
|
||||
export * from "./simple-shipping-tax-rate-factory"
|
||||
export * from "./simple-tax-rate-factory"
|
||||
export * from "./simple-shipping-option-factory"
|
||||
export * from "./simple-shipping-method-factory"
|
||||
export * from "./simple-product-type-tax-rate-factory"
|
||||
export * from "./simple-store-factory"
|
||||
@@ -0,0 +1,34 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { Address } from "@medusajs/medusa"
|
||||
|
||||
export type AddressFactoryData = {
|
||||
first_name?: string
|
||||
last_name?: string
|
||||
country_code?: string
|
||||
address_1?: string
|
||||
postal_code?: string
|
||||
}
|
||||
|
||||
export const simpleAddressFactory = async (
|
||||
connection: Connection,
|
||||
data: AddressFactoryData = {},
|
||||
seed?: number
|
||||
): Promise<Address> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const address = manager.create(Address, {
|
||||
id: `simple-id-${Math.random() * 1000}`,
|
||||
first_name: data.first_name || faker.name.firstName(),
|
||||
last_name: data.last_name || faker.name.lastName(),
|
||||
country_code: data.country_code || "us",
|
||||
address_1: data.address_1 || faker.address.streetAddress(),
|
||||
postal_code: data.postal_code || faker.address.zipCode(),
|
||||
})
|
||||
|
||||
return await manager.save(address)
|
||||
}
|
||||
70
integration-tests/plugins/factories/simple-cart-factory.ts
Normal file
70
integration-tests/plugins/factories/simple-cart-factory.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { Cart } from "@medusajs/medusa"
|
||||
|
||||
import { RegionFactoryData, simpleRegionFactory } from "./simple-region-factory"
|
||||
import {
|
||||
LineItemFactoryData,
|
||||
simpleLineItemFactory,
|
||||
} from "./simple-line-item-factory"
|
||||
import {
|
||||
AddressFactoryData,
|
||||
simpleAddressFactory,
|
||||
} from "./simple-address-factory"
|
||||
import {
|
||||
ShippingMethodFactoryData,
|
||||
simpleShippingMethodFactory,
|
||||
} from "./simple-shipping-method-factory"
|
||||
|
||||
export type CartFactoryData = {
|
||||
id?: string
|
||||
region?: RegionFactoryData | string
|
||||
email?: string | null
|
||||
line_items?: LineItemFactoryData[]
|
||||
shipping_address?: AddressFactoryData
|
||||
shipping_methods?: ShippingMethodFactoryData[]
|
||||
}
|
||||
|
||||
export const simpleCartFactory = async (
|
||||
connection: Connection,
|
||||
data: CartFactoryData = {},
|
||||
seed: number
|
||||
): Promise<Cart> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
let regionId: string
|
||||
if (typeof data.region === "string") {
|
||||
regionId = data.region
|
||||
} else {
|
||||
const region = await simpleRegionFactory(connection, data.region)
|
||||
regionId = region.id
|
||||
}
|
||||
const address = await simpleAddressFactory(connection, data.shipping_address)
|
||||
|
||||
const id = data.id || `simple-cart-${Math.random() * 1000}`
|
||||
const toSave = manager.create(Cart, {
|
||||
id,
|
||||
email:
|
||||
typeof data.email !== "undefined" ? data.email : faker.internet.email(),
|
||||
region_id: regionId,
|
||||
shipping_address_id: address.id,
|
||||
})
|
||||
|
||||
const cart = await manager.save(toSave)
|
||||
|
||||
const shippingMethods = data.shipping_methods || []
|
||||
for (const sm of shippingMethods) {
|
||||
await simpleShippingMethodFactory(connection, { ...sm, cart_id: id })
|
||||
}
|
||||
|
||||
const items = data.line_items
|
||||
for (const item of items) {
|
||||
await simpleLineItemFactory(connection, { ...item, cart_id: id })
|
||||
}
|
||||
|
||||
return cart
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import {
|
||||
Discount,
|
||||
DiscountRule,
|
||||
DiscountRuleType,
|
||||
AllocationType,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
export type DiscountRuleFactoryData = {
|
||||
type?: DiscountRuleType
|
||||
value?: number
|
||||
allocation?: AllocationType
|
||||
}
|
||||
|
||||
export type DiscountFactoryData = {
|
||||
id?: string
|
||||
code?: string
|
||||
is_dynamic?: boolean
|
||||
rule?: DiscountRuleFactoryData
|
||||
regions?: string[]
|
||||
}
|
||||
|
||||
export const simpleDiscountFactory = async (
|
||||
connection: Connection,
|
||||
data: DiscountFactoryData = {},
|
||||
seed?: number
|
||||
): Promise<Discount> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const ruleData = data.rule ?? {}
|
||||
const ruleToSave = manager.create(DiscountRule, {
|
||||
type: ruleData.type ?? DiscountRuleType.PERCENTAGE,
|
||||
value: ruleData.value ?? 10,
|
||||
allocation: ruleData.allocation ?? AllocationType.TOTAL,
|
||||
})
|
||||
|
||||
const dRule = await manager.save(ruleToSave)
|
||||
|
||||
const toSave = manager.create(Discount, {
|
||||
id: data.id,
|
||||
is_dynamic: data.is_dynamic ?? false,
|
||||
is_disabled: false,
|
||||
rule_id: dRule.id,
|
||||
code: data.code ?? "TESTCODE",
|
||||
regions: data.regions?.map((r) => ({ id: r })) || [],
|
||||
})
|
||||
|
||||
const discount = await manager.save(toSave)
|
||||
return discount
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { LineItem, LineItemTaxLine } from "@medusajs/medusa"
|
||||
|
||||
type TaxLineFactoryData = {
|
||||
rate: number
|
||||
code: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export type LineItemFactoryData = {
|
||||
id?: string
|
||||
cart_id?: string
|
||||
order_id?: string
|
||||
variant_id: string | null
|
||||
title?: string
|
||||
description?: string
|
||||
thumbnail?: string
|
||||
should_merge?: boolean
|
||||
allow_discounts?: boolean
|
||||
unit_price?: number
|
||||
quantity?: number
|
||||
fulfilled_quantity?: boolean
|
||||
shipped_quantity?: boolean
|
||||
returned_quantity?: boolean
|
||||
tax_lines?: TaxLineFactoryData[]
|
||||
}
|
||||
|
||||
export const simpleLineItemFactory = async (
|
||||
connection: Connection,
|
||||
data: LineItemFactoryData,
|
||||
seed?: number
|
||||
): Promise<LineItem> => {
|
||||
if (
|
||||
typeof data.cart_id === "undefined" &&
|
||||
typeof data.order_id === "undefined"
|
||||
) {
|
||||
throw Error()
|
||||
}
|
||||
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
Math
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const id = data.id || `simple-line-${Math.random() * 1000}`
|
||||
const toSave = manager.create(LineItem, {
|
||||
id,
|
||||
cart_id: data.cart_id,
|
||||
order_id: data.order_id,
|
||||
title: data.title || faker.commerce.productName(),
|
||||
description: data.description || "",
|
||||
thumbnail: data.thumbnail || "",
|
||||
should_merge:
|
||||
typeof data.should_merge !== "undefined" ? data.should_merge : true,
|
||||
allow_discounts:
|
||||
typeof data.allow_discounts !== "undefined" ? data.allow_discounts : true,
|
||||
unit_price: typeof data.unit_price !== "undefined" ? data.unit_price : 100,
|
||||
variant_id: data.variant_id,
|
||||
quantity: data.quantity || 1,
|
||||
fulfilled_quantity: data.fulfilled_quantity || null,
|
||||
shipped_quantity: data.shipped_quantity || null,
|
||||
returned_quantity: data.returned_quantity || null,
|
||||
})
|
||||
|
||||
const line = await manager.save(toSave)
|
||||
|
||||
if (typeof data.tax_lines !== "undefined") {
|
||||
const taxLinesToSave = data.tax_lines.map((tl) =>
|
||||
manager.create(LineItemTaxLine, {
|
||||
item_id: id,
|
||||
rate: tl.rate,
|
||||
code: tl.code,
|
||||
name: tl.name,
|
||||
})
|
||||
)
|
||||
|
||||
await manager.save(taxLinesToSave)
|
||||
}
|
||||
|
||||
return line
|
||||
}
|
||||
110
integration-tests/plugins/factories/simple-order-factory.ts
Normal file
110
integration-tests/plugins/factories/simple-order-factory.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import {
|
||||
Customer,
|
||||
Order,
|
||||
PaymentStatus,
|
||||
FulfillmentStatus,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
import {
|
||||
DiscountFactoryData,
|
||||
simpleDiscountFactory,
|
||||
} from "./simple-discount-factory"
|
||||
import { RegionFactoryData, simpleRegionFactory } from "./simple-region-factory"
|
||||
import {
|
||||
LineItemFactoryData,
|
||||
simpleLineItemFactory,
|
||||
} from "./simple-line-item-factory"
|
||||
import {
|
||||
AddressFactoryData,
|
||||
simpleAddressFactory,
|
||||
} from "./simple-address-factory"
|
||||
import {
|
||||
ShippingMethodFactoryData,
|
||||
simpleShippingMethodFactory,
|
||||
} from "./simple-shipping-method-factory"
|
||||
|
||||
export type OrderFactoryData = {
|
||||
id?: string
|
||||
payment_status?: PaymentStatus
|
||||
fulfillment_status?: FulfillmentStatus
|
||||
region?: RegionFactoryData | string
|
||||
email?: string | null
|
||||
currency_code?: string
|
||||
tax_rate?: number | null
|
||||
line_items?: LineItemFactoryData[]
|
||||
discounts?: DiscountFactoryData[]
|
||||
shipping_address?: AddressFactoryData
|
||||
shipping_methods?: ShippingMethodFactoryData[]
|
||||
}
|
||||
|
||||
export const simpleOrderFactory = async (
|
||||
connection: Connection,
|
||||
data: OrderFactoryData = {},
|
||||
seed: number
|
||||
): Promise<Order> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
let currencyCode: string
|
||||
let regionId: string
|
||||
let taxRate: number
|
||||
if (typeof data.region === "string") {
|
||||
currencyCode = data.currency_code
|
||||
regionId = data.region
|
||||
taxRate = data.tax_rate
|
||||
} else {
|
||||
const region = await simpleRegionFactory(connection, data.region)
|
||||
taxRate =
|
||||
typeof data.tax_rate !== "undefined" ? data.tax_rate : region.tax_rate
|
||||
currencyCode = region.currency_code
|
||||
regionId = region.id
|
||||
}
|
||||
const address = await simpleAddressFactory(connection, data.shipping_address)
|
||||
|
||||
const customerToSave = manager.create(Customer, {
|
||||
email:
|
||||
typeof data.email !== "undefined" ? data.email : faker.internet.email(),
|
||||
})
|
||||
const customer = await manager.save(customerToSave)
|
||||
|
||||
let discounts = []
|
||||
if (typeof data.discounts !== "undefined") {
|
||||
discounts = await Promise.all(
|
||||
data.discounts.map((d) => simpleDiscountFactory(connection, d, seed))
|
||||
)
|
||||
}
|
||||
|
||||
const id = data.id || `simple-order-${Math.random() * 1000}`
|
||||
const toSave = manager.create(Order, {
|
||||
id,
|
||||
discounts,
|
||||
payment_status: data.payment_status ?? PaymentStatus.AWAITING,
|
||||
fulfillment_status:
|
||||
data.fulfillment_status ?? FulfillmentStatus.NOT_FULFILLED,
|
||||
customer_id: customer.id,
|
||||
email: customer.email,
|
||||
region_id: regionId,
|
||||
currency_code: currencyCode,
|
||||
tax_rate: taxRate,
|
||||
shipping_address_id: address.id,
|
||||
})
|
||||
|
||||
const order = await manager.save(toSave)
|
||||
|
||||
const shippingMethods = data.shipping_methods || []
|
||||
for (const sm of shippingMethods) {
|
||||
await simpleShippingMethodFactory(connection, { ...sm, order_id: order.id })
|
||||
}
|
||||
|
||||
const items = data.line_items
|
||||
for (const item of items) {
|
||||
await simpleLineItemFactory(connection, { ...item, order_id: id })
|
||||
}
|
||||
|
||||
return order
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import {
|
||||
ShippingProfileType,
|
||||
ShippingProfile,
|
||||
Product,
|
||||
ProductType,
|
||||
ProductOption,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
import {
|
||||
simpleProductVariantFactory,
|
||||
ProductVariantFactoryData,
|
||||
} from "./simple-product-variant-factory"
|
||||
|
||||
export type ProductFactoryData = {
|
||||
id?: string
|
||||
is_giftcard?: boolean
|
||||
title?: string
|
||||
type?: string
|
||||
options?: { id: string; title: string }[]
|
||||
variants?: ProductVariantFactoryData[]
|
||||
}
|
||||
|
||||
export const simpleProductFactory = async (
|
||||
connection: Connection,
|
||||
data: ProductFactoryData = {},
|
||||
seed?: number
|
||||
): Promise<Product> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: ShippingProfileType.DEFAULT,
|
||||
})
|
||||
|
||||
const gcProfile = await manager.findOne(ShippingProfile, {
|
||||
type: ShippingProfileType.GIFT_CARD,
|
||||
})
|
||||
|
||||
let typeId: string
|
||||
if (typeof data.type !== "undefined") {
|
||||
const toSave = manager.create(ProductType, {
|
||||
value: data.type,
|
||||
})
|
||||
const res = await manager.save(toSave)
|
||||
typeId = res.id
|
||||
}
|
||||
|
||||
const prodId = data.id || `simple-product-${Math.random() * 1000}`
|
||||
const toSave = manager.create(Product, {
|
||||
id: prodId,
|
||||
type_id: typeId,
|
||||
title: data.title || faker.commerce.productName(),
|
||||
is_giftcard: data.is_giftcard || false,
|
||||
discountable: !data.is_giftcard,
|
||||
profile_id: data.is_giftcard ? gcProfile.id : defaultProfile.id,
|
||||
})
|
||||
|
||||
const product = await manager.save(toSave)
|
||||
|
||||
const optionId = `${prodId}-option`
|
||||
const options = data.options || [{ id: optionId, title: "Size" }]
|
||||
for (const o of options) {
|
||||
await manager.insert(ProductOption, {
|
||||
id: o.id,
|
||||
title: o.title,
|
||||
product_id: prodId,
|
||||
})
|
||||
}
|
||||
|
||||
const variants = data.variants || [
|
||||
{
|
||||
id: `simple-test-variant-${Math.random() * 1000}`,
|
||||
title: "Test",
|
||||
product_id: prodId,
|
||||
prices: [{ currency: "usd", amount: 100 }],
|
||||
options: [{ option_id: optionId, value: "Large" }],
|
||||
},
|
||||
]
|
||||
|
||||
for (const pv of variants) {
|
||||
const factoryData = {
|
||||
...pv,
|
||||
product_id: prodId,
|
||||
}
|
||||
if (typeof pv.options === "undefined") {
|
||||
factoryData.options = [
|
||||
{ option_id: optionId, value: faker.commerce.productAdjective() },
|
||||
]
|
||||
}
|
||||
await simpleProductVariantFactory(connection, factoryData)
|
||||
}
|
||||
|
||||
return product
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { ProductTaxRate, TaxRate } from "@medusajs/medusa"
|
||||
|
||||
type RateFactoryData = {
|
||||
region_id: string
|
||||
rate?: number | null
|
||||
code?: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
export type ProductTaxRateFactoryData = {
|
||||
product_id: string
|
||||
rate: RateFactoryData | string
|
||||
}
|
||||
|
||||
export const simpleProductTaxRateFactory = async (
|
||||
connection: Connection,
|
||||
data: ProductTaxRateFactoryData,
|
||||
seed?: number
|
||||
): Promise<ProductTaxRate> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
let rateId: string
|
||||
if (typeof data.rate === "string") {
|
||||
rateId = data.rate
|
||||
} else {
|
||||
const newRate = manager.create(TaxRate, {
|
||||
region_id: data.rate.region_id,
|
||||
rate: data.rate.rate,
|
||||
code: data.rate.code || "sales_tax",
|
||||
name: data.rate.name || "Sales Tax",
|
||||
})
|
||||
const rate = await manager.save(newRate)
|
||||
rateId = rate.id
|
||||
}
|
||||
|
||||
const toSave = manager.create(ProductTaxRate, {
|
||||
product_id: data.product_id,
|
||||
rate_id: rateId,
|
||||
})
|
||||
|
||||
return await manager.save(toSave)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { ProductTypeTaxRate, TaxRate } from "@medusajs/medusa"
|
||||
|
||||
type RateFactoryData = {
|
||||
region_id: string
|
||||
rate?: number | null
|
||||
code?: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
export type ProductTypeTaxRateFactoryData = {
|
||||
product_type_id: string
|
||||
rate: RateFactoryData | string
|
||||
}
|
||||
|
||||
export const simpleProductTypeTaxRateFactory = async (
|
||||
connection: Connection,
|
||||
data: ProductTypeTaxRateFactoryData,
|
||||
seed?: number
|
||||
): Promise<ProductTypeTaxRate> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
let rateId: string
|
||||
if (typeof data.rate === "string") {
|
||||
rateId = data.rate
|
||||
} else {
|
||||
const newRate = manager.create(TaxRate, {
|
||||
region_id: data.rate.region_id,
|
||||
rate: data.rate.rate,
|
||||
code: data.rate.code || "sales_tax",
|
||||
name: data.rate.name || "Sales Tax",
|
||||
})
|
||||
const rate = await manager.save(newRate)
|
||||
rateId = rate.id
|
||||
}
|
||||
|
||||
const toSave = manager.create(ProductTypeTaxRate, {
|
||||
product_type_id: data.product_type_id,
|
||||
rate_id: rateId,
|
||||
})
|
||||
|
||||
return await manager.save(toSave)
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import {
|
||||
ProductOptionValue,
|
||||
ProductVariant,
|
||||
MoneyAmount,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
export type ProductVariantFactoryData = {
|
||||
product_id: string
|
||||
id?: string
|
||||
is_giftcard?: boolean
|
||||
inventory_quantity?: number
|
||||
title?: string
|
||||
options?: { option_id: string; value: string }[]
|
||||
prices?: { currency: string; amount: number }[]
|
||||
}
|
||||
|
||||
export const simpleProductVariantFactory = async (
|
||||
connection: Connection,
|
||||
data: ProductVariantFactoryData,
|
||||
seed?: number
|
||||
): Promise<ProductVariant> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const id = data.id || `simple-variant-${Math.random() * 1000}`
|
||||
const toSave = manager.create(ProductVariant, {
|
||||
id,
|
||||
product_id: data.product_id,
|
||||
inventory_quantity:
|
||||
typeof data.inventory_quantity !== "undefined"
|
||||
? data.inventory_quantity
|
||||
: 10,
|
||||
title: data.title || faker.commerce.productName(),
|
||||
})
|
||||
|
||||
const variant = await manager.save(toSave)
|
||||
|
||||
const options = data.options || [{ option_id: "test-option", value: "Large" }]
|
||||
for (const o of options) {
|
||||
await manager.insert(ProductOptionValue, {
|
||||
id: `${o.value}-${o.option_id}`,
|
||||
value: o.value,
|
||||
variant_id: id,
|
||||
option_id: o.option_id,
|
||||
})
|
||||
}
|
||||
|
||||
const prices = data.prices || [{ currency: "usd", amount: 100 }]
|
||||
for (const p of prices) {
|
||||
await manager.insert(MoneyAmount, {
|
||||
id: `${p.currency}-${p.amount}-${Math.random()}`,
|
||||
variant_id: id,
|
||||
currency_code: p.currency,
|
||||
amount: p.amount,
|
||||
})
|
||||
}
|
||||
|
||||
return variant
|
||||
}
|
||||
47
integration-tests/plugins/factories/simple-region-factory.ts
Normal file
47
integration-tests/plugins/factories/simple-region-factory.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { Region } from "@medusajs/medusa"
|
||||
|
||||
export type RegionFactoryData = {
|
||||
id?: string
|
||||
name?: string
|
||||
currency_code?: string
|
||||
tax_rate?: number
|
||||
countries?: string[]
|
||||
automatic_taxes?: boolean
|
||||
}
|
||||
|
||||
export const simpleRegionFactory = async (
|
||||
connection: Connection,
|
||||
data: RegionFactoryData = {},
|
||||
seed?: number
|
||||
): Promise<Region> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const regionId = data.id || `simple-region-${Math.random() * 1000}`
|
||||
const r = manager.create(Region, {
|
||||
id: regionId,
|
||||
name: data.name || "Test Region",
|
||||
currency_code: data.currency_code || "usd",
|
||||
tax_rate: data.tax_rate || 0,
|
||||
payment_providers: [{ id: "test-pay" }],
|
||||
automatic_taxes:
|
||||
typeof data.automatic_taxes !== "undefined" ? data.automatic_taxes : true,
|
||||
})
|
||||
|
||||
const region = await manager.save(r)
|
||||
|
||||
const countries = data.countries || ["us"]
|
||||
|
||||
for (const cc of countries) {
|
||||
await manager.query(
|
||||
`UPDATE "country" SET region_id='${regionId}' WHERE iso_2 = '${cc}'`
|
||||
)
|
||||
}
|
||||
|
||||
return region
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { ShippingMethodTaxLine, ShippingMethod } from "@medusajs/medusa"
|
||||
|
||||
import {
|
||||
ShippingOptionFactoryData,
|
||||
simpleShippingOptionFactory,
|
||||
} from "./simple-shipping-option-factory"
|
||||
|
||||
export type ShippingMethodFactoryData = {
|
||||
id?: string
|
||||
cart_id?: string
|
||||
order_id?: string
|
||||
data?: object
|
||||
price?: number
|
||||
shipping_option: string | ShippingOptionFactoryData
|
||||
tax_lines?: ShippingMethodTaxLine[]
|
||||
}
|
||||
|
||||
export const simpleShippingMethodFactory = async (
|
||||
connection: Connection,
|
||||
data: ShippingMethodFactoryData,
|
||||
seed?: number
|
||||
): Promise<ShippingMethod> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
let shippingOptionId: string
|
||||
if (typeof data.shipping_option === "string") {
|
||||
shippingOptionId = data.shipping_option
|
||||
} else {
|
||||
const option = await simpleShippingOptionFactory(
|
||||
connection,
|
||||
data.shipping_option
|
||||
)
|
||||
shippingOptionId = option.id
|
||||
}
|
||||
|
||||
const id = data.id || `simple-sm-${Math.random() * 1000}`
|
||||
const toSave = manager.create(ShippingMethod, {
|
||||
id,
|
||||
cart_id: data.cart_id,
|
||||
order_id: data.order_id,
|
||||
shipping_option_id: shippingOptionId,
|
||||
data: data.data || {},
|
||||
price: typeof data.price !== "undefined" ? data.price : 500,
|
||||
})
|
||||
|
||||
const shippingMethod = await manager.save(toSave)
|
||||
|
||||
if (typeof data.tax_lines !== "undefined") {
|
||||
const taxLinesToSave = data.tax_lines.map((tl) =>
|
||||
manager.create(ShippingMethodTaxLine, {
|
||||
shipping_method_id: shippingMethod.id,
|
||||
rate: tl.rate,
|
||||
code: tl.code || "default",
|
||||
name: tl.name || "default",
|
||||
})
|
||||
)
|
||||
|
||||
await manager.save(taxLinesToSave)
|
||||
}
|
||||
|
||||
return shippingMethod
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import {
|
||||
ShippingOptionPriceType,
|
||||
ShippingProfile,
|
||||
ShippingOption,
|
||||
ShippingProfileType,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
export type ShippingOptionFactoryData = {
|
||||
name?: string
|
||||
region_id: string
|
||||
is_return?: boolean
|
||||
is_giftcard?: boolean
|
||||
price?: number
|
||||
}
|
||||
|
||||
export const simpleShippingOptionFactory = async (
|
||||
connection: Connection,
|
||||
data: ShippingOptionFactoryData,
|
||||
seed?: number
|
||||
): Promise<ShippingOption> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
const defaultProfile = await manager.findOne(ShippingProfile, {
|
||||
type: ShippingProfileType.DEFAULT,
|
||||
})
|
||||
|
||||
const gcProfile = await manager.findOne(ShippingProfile, {
|
||||
type: ShippingProfileType.GIFT_CARD,
|
||||
})
|
||||
|
||||
const created = manager.create(ShippingOption, {
|
||||
id: `simple-so-${Math.random() * 1000}`,
|
||||
name: data.name || "Test Method",
|
||||
is_return: data.is_return ?? false,
|
||||
region_id: data.region_id,
|
||||
provider_id: "test-ful",
|
||||
profile_id: data.is_giftcard ? gcProfile.id : defaultProfile.id,
|
||||
price_type: ShippingOptionPriceType.FLAT_RATE,
|
||||
data: {},
|
||||
amount: typeof data.price !== "undefined" ? data.price : 500,
|
||||
})
|
||||
const option = await manager.save(created)
|
||||
return option
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { ShippingTaxRate, TaxRate } from "@medusajs/medusa"
|
||||
|
||||
type RateFactoryData = {
|
||||
region_id: string
|
||||
rate?: number | null
|
||||
code?: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
export type ShippingTaxRateFactoryData = {
|
||||
shipping_option_id: string
|
||||
rate: RateFactoryData | string
|
||||
}
|
||||
|
||||
export const simpleShippingTaxRateFactory = async (
|
||||
connection: Connection,
|
||||
data: ShippingTaxRateFactoryData,
|
||||
seed?: number
|
||||
): Promise<ShippingTaxRate> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
let rateId: string
|
||||
if (typeof data.rate === "string") {
|
||||
rateId = data.rate
|
||||
} else {
|
||||
const newRate = manager.create(TaxRate, {
|
||||
region_id: data.rate.region_id,
|
||||
rate: data.rate.rate,
|
||||
code: data.rate.code || "sales_tax",
|
||||
name: data.rate.name || "Sales Tax",
|
||||
})
|
||||
const rate = await manager.save(newRate)
|
||||
rateId = rate.id
|
||||
}
|
||||
|
||||
const toSave = manager.create(ShippingTaxRate, {
|
||||
shipping_option_id: data.shipping_option_id,
|
||||
rate_id: rateId,
|
||||
})
|
||||
|
||||
return await manager.save(toSave)
|
||||
}
|
||||
24
integration-tests/plugins/factories/simple-store-factory.ts
Normal file
24
integration-tests/plugins/factories/simple-store-factory.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { Store } from "@medusajs/medusa"
|
||||
|
||||
export type StoreFactoryData = {
|
||||
swap_link_template?: string
|
||||
}
|
||||
|
||||
export const simpleStoreFactory = async (
|
||||
connection: Connection,
|
||||
data: StoreFactoryData = {},
|
||||
seed?: number
|
||||
): Promise<Store> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
const store = await manager.findOne(Store)
|
||||
|
||||
store.swap_link_template = data.swap_link_template ?? "something/{cart_id}"
|
||||
|
||||
return await manager.save(store)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Connection } from "typeorm"
|
||||
import faker from "faker"
|
||||
import { TaxRate } from "@medusajs/medusa"
|
||||
|
||||
export type TaxRateFactoryData = {
|
||||
region_id: string
|
||||
rate?: number | null
|
||||
code?: string
|
||||
name?: string
|
||||
}
|
||||
|
||||
export const simpleTaxRateFactory = async (
|
||||
connection: Connection,
|
||||
data: TaxRateFactoryData,
|
||||
seed?: number
|
||||
): Promise<TaxRate> => {
|
||||
if (typeof seed !== "undefined") {
|
||||
faker.seed(seed)
|
||||
}
|
||||
|
||||
const manager = connection.manager
|
||||
|
||||
const toSave = manager.create(TaxRate, {
|
||||
region_id: data.region_id,
|
||||
rate:
|
||||
data.rate ?? faker.datatype.number({ min: 0, max: 100, precision: 2 }),
|
||||
code: data.code || faker.random.word(),
|
||||
name: data.name || faker.random.words(2),
|
||||
})
|
||||
|
||||
return await manager.save(toSave)
|
||||
}
|
||||
Reference in New Issue
Block a user