-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core): Improve naming of price calculation strategies
Relates to #307. BREAKING CHANGE: The `TaxCalculationStrategy` has been renamed to `ProductVariantPriceCalculationStrategy` and moved in the VendureCofig from `taxOptions` to `catalogOptions` and its API has been simplified. The `PriceCalculationStrategy` has been renamed to `OrderItemPriceCalculationStrategy`.
- Loading branch information
1 parent
9544dd4
commit ccbebc9
Showing
30 changed files
with
461 additions
and
471 deletions.
There are no files selected for viewing
9 changes: 7 additions & 2 deletions
9
...xtures/test-price-calculation-strategy.ts → ...-order-item-price-calculation-strategy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import { TaxCategory } from '../../entity/tax-category/tax-category.entity'; | ||
import { TaxRate } from '../../entity/tax-rate/tax-rate.entity'; | ||
import { Zone } from '../../entity/zone/zone.entity'; |
File renamed without changes.
File renamed without changes.
184 changes: 184 additions & 0 deletions
184
packages/core/src/config/catalog/default-product-variant-price-calculation-strategy.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
import { | ||
createRequestContext, | ||
MockTaxRateService, | ||
taxCategoryReduced, | ||
taxCategoryStandard, | ||
taxRateDefaultReduced, | ||
taxRateDefaultStandard, | ||
taxRateOtherReduced, | ||
taxRateOtherStandard, | ||
zoneDefault, | ||
zoneOther, | ||
zoneWithNoTaxRate, | ||
} from '../../testing/order-test-utils'; | ||
|
||
import { DefaultProductVariantPriceCalculationStrategy } from './default-product-variant-price-calculation-strategy'; | ||
|
||
describe('DefaultProductVariantPriceCalculationStrategy', () => { | ||
let strategy: DefaultProductVariantPriceCalculationStrategy; | ||
const inputPrice = 6543; | ||
|
||
beforeEach(async () => { | ||
strategy = new DefaultProductVariantPriceCalculationStrategy(); | ||
const mockInjector = { | ||
get: () => { | ||
return new MockTaxRateService(); | ||
}, | ||
} as any; | ||
strategy.init(mockInjector); | ||
}); | ||
|
||
describe('with prices which do not include tax', () => { | ||
it('standard tax, default zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: false }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryStandard, | ||
activeTaxZone: zoneDefault, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
|
||
it('reduced tax, default zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: false }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryReduced, | ||
activeTaxZone: zoneDefault, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
|
||
it('standard tax, other zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: false }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryStandard, | ||
activeTaxZone: zoneOther, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
|
||
it('reduced tax, other zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: false }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryReduced, | ||
activeTaxZone: zoneOther, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
|
||
it('standard tax, unconfigured zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: false }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryReduced, | ||
activeTaxZone: zoneWithNoTaxRate, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('with prices which include tax', () => { | ||
it('standard tax, default zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: true }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryStandard, | ||
activeTaxZone: zoneDefault, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: true, | ||
}); | ||
}); | ||
|
||
it('reduced tax, default zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: true }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryReduced, | ||
activeTaxZone: zoneDefault, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: inputPrice, | ||
priceIncludesTax: true, | ||
}); | ||
}); | ||
|
||
it('standard tax, other zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: true }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryStandard, | ||
activeTaxZone: zoneOther, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: taxRateDefaultStandard.netPriceOf(inputPrice), | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
|
||
it('reduced tax, other zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: true }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryReduced, | ||
activeTaxZone: zoneOther, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: taxRateDefaultReduced.netPriceOf(inputPrice), | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
|
||
it('standard tax, unconfigured zone', () => { | ||
const ctx = createRequestContext({ pricesIncludeTax: true }); | ||
const result = strategy.calculate({ | ||
inputPrice, | ||
taxCategory: taxCategoryStandard, | ||
activeTaxZone: zoneWithNoTaxRate, | ||
ctx, | ||
}); | ||
|
||
expect(result).toEqual({ | ||
price: taxRateDefaultStandard.netPriceOf(inputPrice), | ||
priceIncludesTax: false, | ||
}); | ||
}); | ||
}); | ||
}); |
48 changes: 48 additions & 0 deletions
48
packages/core/src/config/catalog/default-product-variant-price-calculation-strategy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { Injector } from '../../common/injector'; | ||
import { PriceCalculationResult } from '../../common/types/common-types'; | ||
import { idsAreEqual } from '../../common/utils'; | ||
import { TaxRateService } from '../../service/services/tax-rate.service'; | ||
|
||
import { | ||
ProductVariantPriceCalculationArgs, | ||
ProductVariantPriceCalculationStrategy, | ||
} from './product-variant-price-calculation-strategy'; | ||
|
||
/** | ||
* @description | ||
* A default ProductVariant price calculation function. | ||
* | ||
* @docsCategory tax | ||
*/ | ||
export class DefaultProductVariantPriceCalculationStrategy implements ProductVariantPriceCalculationStrategy { | ||
private taxRateService: TaxRateService; | ||
|
||
init(injector: Injector) { | ||
this.taxRateService = injector.get(TaxRateService); | ||
} | ||
|
||
calculate(args: ProductVariantPriceCalculationArgs): PriceCalculationResult { | ||
const { inputPrice, activeTaxZone, ctx, taxCategory } = args; | ||
let price = inputPrice; | ||
let priceIncludesTax = false; | ||
const taxRate = this.taxRateService.getApplicableTaxRate(activeTaxZone, taxCategory); | ||
|
||
if (ctx.channel.pricesIncludeTax) { | ||
const isDefaultZone = idsAreEqual(activeTaxZone.id, ctx.channel.defaultTaxZone.id); | ||
if (isDefaultZone) { | ||
priceIncludesTax = true; | ||
} else { | ||
const taxRateForDefaultZone = this.taxRateService.getApplicableTaxRate( | ||
ctx.channel.defaultTaxZone, | ||
taxCategory, | ||
); | ||
price = taxRateForDefaultZone.netPriceOf(inputPrice); | ||
} | ||
} | ||
|
||
return { | ||
price, | ||
priceIncludesTax, | ||
}; | ||
} | ||
} |
38 changes: 38 additions & 0 deletions
38
packages/core/src/config/catalog/product-variant-price-calculation-strategy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { RequestContext } from '../../api/common/request-context'; | ||
import { PriceCalculationResult } from '../../common/types/common-types'; | ||
import { InjectableStrategy } from '../../common/types/injectable-strategy'; | ||
import { TaxCategory, Zone } from '../../entity/index'; | ||
import { TaxRateService } from '../../service/services/tax-rate.service'; | ||
|
||
/** | ||
* @description | ||
* Defines how ProductVariant are calculated based on the input price, tax zone and current request context. | ||
* | ||
* @docsCategory tax | ||
*/ | ||
export interface ProductVariantPriceCalculationStrategy extends InjectableStrategy { | ||
calculate(args: ProductVariantPriceCalculationArgs): PriceCalculationResult; | ||
} | ||
|
||
/** | ||
* @description | ||
* The arguments passed the the `calculate` method of the configured {@link ProductVariantPriceCalculationStrategy}. | ||
* | ||
* @docsCategory tax | ||
* @docsPage Tax Types | ||
*/ | ||
export interface ProductVariantPriceCalculationArgs { | ||
inputPrice: number; | ||
taxCategory: TaxCategory; | ||
activeTaxZone: Zone; | ||
ctx: RequestContext; | ||
} | ||
|
||
/** | ||
* @description | ||
* This is an alias of {@link ProductVariantPriceCalculationStrategy} to preserve compatibility when upgrading. | ||
* | ||
* @deprecated Use ProductVariantPriceCalculationStrategy | ||
* @docsCategory Orders | ||
*/ | ||
export interface TaxCalculationStrategy extends ProductVariantPriceCalculationStrategy {} |
Oops, something went wrong.