feat(medusa): Tax-inclusive pricing (#2131)

* add feature flag for tax inclusive pricing

* update db model for TIP

* add migration

* set featureflag column decorators

* remove unused prop

* update tests to reflect feature_flags as any array

* fix types

* reference key from featureFlag file

* use feature flag key in models

* fix copy paste mistake

* unify spelling

* Create gorgeous-experts-guess.md

* feat(medusa): create/update endpoints of currency/region/price-lists/shipping-options should allow to pass includes_tax

* test(integration): continue to add some integration test

* test(integration): continue to add some integration test

* test(unit): Fix region service tests

* fix(medusa): API unit tests flags management

* feat(medusa): Minor cleanup

* style(medusa): Fix typo

* fix(medusa): rebase

* feat(medusa): Replace old tag with the new one

* feat(medusa): revert flag

* feat(medusa): Cleanup

* feat(medusa): feedback

* feat(medusa): Rename currency retrieve method

* test(medudsa): fix unit tests

* chore(medusa): fix oas

* feat(medusa): ShippingMethod should include tax setting from parent option (#2021)

* feat(medusa): Shipping method should includes tax from parent options

* feat(medusa): Condition the includes tax flag to the availability of the feature and add some other tests

* test(integration): Move cart/order ff test in separate files

* fix: snapshots folder

* fix(integration): snapshots

* Create calm-baboons-sit.md

* test(integration): file naming

Co-authored-by: Carlos R. L. Rodrigues <rodrigolr@gmail.com>

* Feat/tax inclusive pricing extend price selection strategy (#2087)

* initial changes to price selection strategy including unit tests

* typing for tax calculation

* update types and remove region and currency from prices results

* fix casing

* include tax calculation in priceselectionstrategy

* integration tests for tax inclusive pricing price calculations

* fix build

* include tax inclusive considerations when calculating tax fields for variants

* include only "includes_tax" fields from currency and region joins

* test to see errors in pipelines

* conditionally join featureflagged fields

* add "includes_tax" to price list factory

* add tests for tax inclusive price list prices and currency prices

* fix unit tests

* refactor pricing array checks to expect arraycontaining

* undo error handler

* Feat/tax inclusive pricing flag on generated lineitems (#2108)

* include tax inclusive pricing flag on generated lineitems

* initial addition of tax inclusivity for lineitem service

* add generate test to ensure that includes_tax is set when returned from price selection strategy

* add integration test for generating lineitem including tax

* add test for negative tax inclusion

* add tests for mixed pricing

* add negative test for setting tax exclusivity

* restructure the setting of includes_tax on lineitems

* fix: update cwd to be correct in cart test

* feat(medusa): Line item totals calculations (#2123)

* feat(medusa): Update totals and tax calculation way to calculate the totals

* feat(medusa): remove region feetching from decorate total

* feat(medusa): cleanup

* test(medusa): fix tax calculation tests

* comment

* test(integration): cleanup

* test(integration): cleanup

* fix(medusa): return service missing await

* feat(medusa): cleanup

* feat(medusa): cleanup

* test(integration): fix data

* feat(medusa): improve tax calculation readability

* test(medusa): improve tax calculation structure case

Co-authored-by: Sebastian Rindom <skrindom@gmail.com>

* Feat(medusa): tax inclusive pricing in shipping method tax (#2125)

* initial implementation and test

* include tax inclusive calculations for getting shipping options

* remove inaccurate comment

* remove console log

* refactor how prices and taxes are set for shipping methods

* fix integration tests

* remove verbose flag

* fix integration tests

* remove console log

* format util

* use util in price service and tax strategy

* fix faulty integration test

* undo tax calculation strategy changes in favor or Carlos' pr

* undo changes to tax calculation strategy tests

* round tax amount

* feat(medusa): cleanup calculate tax amount utils and its usage (#2136)

* feat(medusa): Refund line totals calculation (#2139)

Rely on the update of the following pr https://github.com/medusajs/medusa/pull/2136

**WIP Missing integration tests**

**What**

Update the totals calculation on the refund line to include the notion of tax inclusive

**Test**

- Update and add new tests around the refund


Fixes CORE-482

* feat(medusa): Tax inclusive discounts calculations (#2137)

**What**

- Calculate line adjustments correctly taking into account the tax inclusivity
- fix totals getLineItemTotals by adjusting the sub total with the original tax amount instead of the tax amount when the unit price includes the taxes

**Tests**
- The tests create a cart with a percentage discount of 15%, the cart includes 2 items mixing the tax inclusive and validate the items on the result cart as well as the totals on each item. I ve based my calculation validation based on what we have done + some articles around discount apply on price without taxes to validate the output.,
FIXES CORE-477

* Chore: shipping methods tax inclusive total (#2130)

* chore: calculate tax inclusive shipping methods

* chore: additional tests and check undefined tax_rate (#2157)

* chore: additional tests and check undefined tax_rate

* fix: naming + correct price type check

* fix: remove price_includes_tax from type

* fix: remove price_includes_tax from type

Co-authored-by: Philip Korsholm <philip.korsholm@hotmail.com>
Co-authored-by: adrien2p <adrien.deperetti@gmail.com>
Co-authored-by: Carlos R. L. Rodrigues <rodrigolr@gmail.com>
Co-authored-by: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com>
Co-authored-by: Sebastian Rindom <skrindom@gmail.com>
Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com>
This commit is contained in:
Oliver Windall Juhl
2022-09-07 10:21:29 +02:00
committed by GitHub
co-authored by Philip Korsholm adrien2p Carlos R. L. Rodrigues Philip Korsholm Sebastian Rindom Carlos R. L. Rodrigues
parent af80e0fd2e
commit cbb7dd9787
105 changed files with 6788 additions and 1040 deletions
+1
View File
@@ -17,3 +17,4 @@ export * from "./simple-product-type-tax-rate-factory"
export * from "./simple-price-list-factory"
export * from "./simple-batch-job-factory"
export * from "./simple-sales-channel-factory"
export * from "./simple-custom-shipping-option-factory"
@@ -0,0 +1,36 @@
import { Connection } from "typeorm"
import faker from "faker"
import {
CustomShippingOption,
} from "@medusajs/medusa"
export type CustomShippingOptionFactoryData = {
id?: string
cart_id: string
shipping_option_id: string
price?: number
metadata?: Record<string, unknown>
}
export const simpleCustomShippingOptionFactory = async (
connection: Connection,
data: CustomShippingOptionFactoryData,
seed?: number
): Promise<CustomShippingOption> => {
if (typeof seed !== "undefined") {
faker.seed(seed)
}
const manager = connection.manager
const customShippingOptionData = {
id: data.id ?? `custon-simple-so-${Math.random() * 1000}`,
price: typeof data.price !== "undefined" ? data.price : 500,
cart_id: data.cart_id,
shipping_option_id: data.shipping_option_id,
metadata: data.metadata ?? {}
}
const created = manager.create(CustomShippingOption, customShippingOptionData)
return await manager.save(created)
}
@@ -12,7 +12,7 @@ import { DiscountConditionJoinTableForeignKey } from "@medusajs/medusa/dist/repo
import faker from "faker"
import { Connection } from "typeorm"
export type DiscuntConditionFactoryData = {
export type DiscountConditionFactoryData = {
id?: string
rule_id: string
type: DiscountConditionType
@@ -67,7 +67,7 @@ const getJoinTableResourceIdentifiers = (type: string) => {
export const simpleDiscountConditionFactory = async (
connection: Connection,
data: DiscuntConditionFactoryData,
data: DiscountConditionFactoryData,
seed?: number
): Promise<void> => {
if (typeof seed !== "undefined") {
@@ -7,7 +7,7 @@ import {
import faker from "faker"
import { Connection } from "typeorm"
import {
DiscuntConditionFactoryData,
DiscountConditionFactoryData,
simpleDiscountConditionFactory,
} from "./simple-discount-condition-factory"
@@ -15,7 +15,7 @@ export type DiscountRuleFactoryData = {
type?: DiscountRuleType
value?: number
allocation?: AllocationType
conditions: DiscuntConditionFactoryData[]
conditions: DiscountConditionFactoryData[]
}
export type DiscountFactoryData = {
@@ -24,6 +24,8 @@ export type DiscountFactoryData = {
is_dynamic?: boolean
rule?: DiscountRuleFactoryData
regions?: string[]
starts_at?: Date
ends_at?: Date
}
export const simpleDiscountFactory = async (
@@ -37,7 +39,7 @@ export const simpleDiscountFactory = async (
const manager = connection.manager
const ruleData = data.rule ?? {}
const ruleData = data.rule ?? ({} as DiscountRuleFactoryData)
const ruleToSave = manager.create(DiscountRule, {
type: ruleData.type ?? DiscountRuleType.PERCENTAGE,
value: ruleData.value ?? 10,
@@ -63,8 +65,9 @@ export const simpleDiscountFactory = async (
rule_id: dRule.id,
code: data.code ?? "TESTCODE",
regions: data.regions?.map((r) => ({ id: r })) || [],
starts_at: data.starts_at,
ends_at: data.ends_at,
})
const discount = await manager.save(toSave)
return discount
return await manager.save(toSave)
}
@@ -30,6 +30,7 @@ export type LineItemFactoryData = {
returned_quantity?: boolean
tax_lines?: TaxLineFactoryData[]
adjustments: LineItemAdjustmentFactoryData[]
includes_tax?: boolean
}
export const simpleLineItemFactory = async (
@@ -70,6 +71,7 @@ export const simpleLineItemFactory = async (
shipped_quantity: data.shipped_quantity || null,
returned_quantity: data.returned_quantity || null,
adjustments: data.adjustments,
includes_tax: data.includes_tax,
})
const line = await manager.save(toSave)
@@ -26,6 +26,7 @@ export type PriceListFactoryData = {
ends_at?: Date
customer_groups?: string[]
prices?: ProductListPrice[]
includes_tax?: boolean
}
export const simplePriceListFactory = async (
@@ -59,6 +60,7 @@ export const simplePriceListFactory = async (
starts_at: data.starts_at || null,
ends_at: data.ends_at || null,
customer_groups: customerGroups,
includes_tax: data.includes_tax,
}
const toSave = manager.create(PriceList, toCreate)
@@ -10,6 +10,8 @@ export type RegionFactoryData = {
countries?: string[]
automatic_taxes?: boolean
gift_cards_taxable?: boolean
fulfillment_providers?: { id: string }[]
includes_tax?: boolean
}
export const simpleRegionFactory = async (
@@ -30,7 +32,9 @@ export const simpleRegionFactory = async (
currency_code: data.currency_code || "usd",
tax_rate: data.tax_rate || 0,
payment_providers: [{ id: "test-pay" }],
fulfillment_providers: data.fulfillment_providers ?? [{ id: "test-ful" }],
gift_cards_taxable: data.gift_cards_taxable ?? true,
includes_tax: data.includes_tax,
automatic_taxes:
typeof data.automatic_taxes !== "undefined" ? data.automatic_taxes : true,
})
@@ -15,6 +15,7 @@ export type ShippingMethodFactoryData = {
price?: number
shipping_option: string | ShippingOptionFactoryData
tax_lines?: ShippingMethodTaxLine[]
includes_tax?: boolean
}
export const simpleShippingMethodFactory = async (
@@ -47,6 +48,7 @@ export const simpleShippingMethodFactory = async (
shipping_option_id: shippingOptionId,
data: data.data || {},
price: typeof data.price !== "undefined" ? data.price : 500,
includes_tax: data.includes_tax,
})
const shippingMethod = await manager.save(toSave)
@@ -8,12 +8,14 @@ import faker from "faker"
import { Connection } from "typeorm"
export type ShippingOptionFactoryData = {
id?: string
name?: string
region_id: string
is_return?: boolean
is_giftcard?: boolean
price?: number
price_type?: ShippingOptionPriceType
includes_tax?: boolean
data?: object
}
@@ -35,8 +37,8 @@ export const simpleShippingOptionFactory = async (
type: ShippingProfileType.GIFT_CARD,
})
const created = manager.create(ShippingOption, {
id: `simple-so-${Math.random() * 1000}`,
const shippingOptionData = {
id: data.id ?? `simple-so-${Math.random() * 1000}`,
name: data.name || "Test Method",
is_return: data.is_return ?? false,
region_id: data.region_id,
@@ -45,7 +47,15 @@ export const simpleShippingOptionFactory = async (
price_type: data.price_type ?? ShippingOptionPriceType.FLAT_RATE,
data: data.data ?? {},
amount: typeof data.price !== "undefined" ? data.price : 500,
})
const option = await manager.save(created)
return option
}
// This is purposefully managed out of the original object for the purpose of separating the data linked to a feature flag
// MEDUSA_FF_TAX_INCLUSIVE_PRICING
const { includes_tax } = data
if (typeof includes_tax !== "undefined") {
shippingOptionData["includes_tax"] = includes_tax
}
const created = manager.create(ShippingOption, shippingOptionData)
return await manager.save(created)
}