@unchainedshop/utils 2.2.3 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ export type PricingInterface = {
2
+ taxSum: () => number;
3
+ gross: () => number;
4
+ };
5
+ export declare const roundToNext: (value: number, precision: number) => number;
6
+ export declare const resolveRatioAndTaxDivisorForPricingSheet: (pricing: PricingInterface, total: number) => {
7
+ ratio: number;
8
+ taxDivisor: number;
9
+ };
10
+ export declare const calculateAmountToSplit: (configuration: {
11
+ rate?: number;
12
+ fixedRate?: number;
13
+ alreadyDeducted?: number;
14
+ }, amount: number) => number;
15
+ export declare const applyRate: (configuration: {
16
+ fixedRate?: number;
17
+ rate?: number;
18
+ }, amount: any) => number;
19
+ export declare const resolveAmountAndTax: ({ ratio, taxDivisor }: {
20
+ ratio?: number;
21
+ taxDivisor?: number;
22
+ }, amount: number) => number[];
23
+ export declare const applyDiscountToMultipleShares: (shares: any, amount: any) => any;
@@ -0,0 +1,44 @@
1
+ export const roundToNext = (value, precision) => Math.ceil(value / precision) * precision;
2
+ export const resolveRatioAndTaxDivisorForPricingSheet = (pricing, total) => {
3
+ if (total === 0 || !pricing) {
4
+ return {
5
+ ratio: 1,
6
+ taxDivisor: 1,
7
+ };
8
+ }
9
+ const tax = pricing.taxSum();
10
+ const gross = pricing.gross();
11
+ if (gross - tax === 0) {
12
+ return {
13
+ ratio: 0,
14
+ taxDivisor: 0,
15
+ };
16
+ }
17
+ return {
18
+ ratio: gross / total,
19
+ taxDivisor: gross / (gross - tax),
20
+ };
21
+ };
22
+ export const calculateAmountToSplit = (configuration, amount) => {
23
+ const deductionAmount = configuration.rate
24
+ ? amount * configuration.rate
25
+ : Math.min(configuration.fixedRate, amount);
26
+ const leftInDiscount = Math.max(0, deductionAmount - (configuration.alreadyDeducted ?? 0));
27
+ return leftInDiscount;
28
+ };
29
+ export const applyRate = (configuration, amount) => {
30
+ const { rate, fixedRate } = configuration;
31
+ return rate ? amount * rate : Math.min(fixedRate || 0, amount);
32
+ };
33
+ export const resolveAmountAndTax = ({ ratio, taxDivisor }, amount) => {
34
+ const shareAmount = Number.isFinite(ratio) ? amount * ratio : 0;
35
+ const shareTaxAmount = Number.isFinite(taxDivisor) && taxDivisor !== 0 ? shareAmount - shareAmount / taxDivisor : 0;
36
+ return [shareAmount, shareTaxAmount];
37
+ };
38
+ export const applyDiscountToMultipleShares = (shares, amount) => {
39
+ return shares.reduce(([currentDiscountAmount, currentTaxAmount], share) => {
40
+ const [shareAmount, shareTaxAmount] = resolveAmountAndTax(share, amount);
41
+ return [currentDiscountAmount + shareAmount, currentTaxAmount + shareTaxAmount];
42
+ }, [0, 0]);
43
+ };
44
+ //# sourceMappingURL=calculation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calculation.js","sourceRoot":"","sources":["../src/calculation.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,SAAiB,EAAE,EAAE,CAC9D,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,SAAS,CAAC;AAE3C,MAAM,CAAC,MAAM,wCAAwC,GAAG,CAAC,OAAyB,EAAE,KAAa,EAAE,EAAE;IACnG,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;QAC3B,OAAO;YACL,KAAK,EAAE,CAAC;YACR,UAAU,EAAE,CAAC;SACd,CAAC;KACH;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,GAAG,KAAK,CAAC,EAAE;QACrB,OAAO;YACL,KAAK,EAAE,CAAC;YACR,UAAU,EAAE,CAAC;SACd,CAAC;KACH;IACD,OAAO;QACL,KAAK,EAAE,KAAK,GAAG,KAAK;QACpB,UAAU,EAAE,KAAK,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC;KAClC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,aAA8E,EAC9E,MAAc,EACd,EAAE;IACF,MAAM,eAAe,GAAG,aAAa,CAAC,IAAI;QACxC,CAAC,CAAC,MAAM,GAAG,aAAa,CAAC,IAAI;QAC7B,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAE9C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,eAAe,GAAG,CAAC,aAAa,CAAC,eAAe,IAAI,CAAC,CAAC,CAAC,CAAC;IAC3F,OAAO,cAAc,CAAC;AACxB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,aAAoD,EAAE,MAAM,EAAE,EAAE;IACxF,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC;IAC1C,OAAO,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AACjE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,EAAE,KAAK,EAAE,UAAU,EAA2C,EAC9D,MAAc,EACd,EAAE;IACF,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,cAAc,GAClB,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,UAAU,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,OAAO,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;AACvC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;IAC9D,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,CAAC,qBAAqB,EAAE,gBAAgB,CAAC,EAAE,KAAK,EAAE,EAAE;QACnD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACzE,OAAO,CAAC,qBAAqB,GAAG,WAAW,EAAE,gBAAgB,GAAG,cAAc,CAAC,CAAC;IAClF,CAAC,EACD,CAAC,CAAC,EAAE,CAAC,CAAC,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import 'abort-controller/polyfill.js';
2
- import LRU from 'lru-cache';
2
+ import { LRUCache } from 'lru-cache';
3
3
  import { systemLocale } from './locale-helpers.js';
4
4
  const { NODE_ENV } = process.env;
5
5
  const ttl = NODE_ENV === 'production' ? 1000 * 10 : 0; // 10 seconds or 0 seconds
6
- const textCache = new LRU({ max: 50000, ttl });
6
+ const textCache = new LRUCache({ max: 50000, ttl });
7
7
  const extendSelectorWithLocale = (selector, locale) => {
8
8
  const localeSelector = {
9
9
  locale: { $in: [locale.normalized, locale.language] },
@@ -1 +1 @@
1
- {"version":3,"file":"find-localized-text.js","sourceRoot":"","sources":["../src/find-localized-text.ts"],"names":[],"mappings":"AAAA,OAAO,8BAA8B,CAAC;AACtC,OAAO,GAAG,MAAM,WAAW,CAAC;AAE5B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAEjC,MAAM,GAAG,GAAG,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B;AAEjF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;AAE/C,MAAM,wBAAwB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;IACpD,MAAM,cAAc,GAAG;QACrB,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE;KACtD,CAAC;IACF,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,QAAQ,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAC7B,UAAyB,EACzB,QAAmB,EACnB,MAAc,EACF,EAAE;IACd,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAC9B,CAAC,EAAE,UAAU,CAAC,cAAc;QAC5B,CAAC,EAAE,QAAQ;QACX,CAAC,EAAE,MAAM;KACV,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE3C,IAAI,UAAU;QAAE,OAAO,UAAe,CAAC;IAEvC,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,wBAAwB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;QAC5F,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;KACtB,CAAC,CAAC;IACH,IAAI,gBAAgB,EAAE;QACpB,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QAC1C,OAAO,gBAAqB,CAAC;KAC9B;IAED,IAAI,YAAY,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE;QACjD,MAAM,mBAAmB,GAAG,MAAM,UAAU,CAAC,OAAO,CAClD,wBAAwB,CAAC,QAAQ,EAAE,YAAY,CAAC,EAChD;YACE,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;SACtB,CACF,CAAC;QACF,IAAI,mBAAmB,EAAE;YACvB,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;YAC7C,OAAO,mBAAwB,CAAC;SACjC;KACF;IAED,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE;QACnD,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;KACtB,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACnC,OAAO,SAAc,CAAC;AACxB,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
1
+ {"version":3,"file":"find-localized-text.js","sourceRoot":"","sources":["../src/find-localized-text.ts"],"names":[],"mappings":"AAAA,OAAO,8BAA8B,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;AAEjC,MAAM,GAAG,GAAG,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B;AAEjF,MAAM,SAAS,GAAG,IAAI,QAAQ,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;AAEpD,MAAM,wBAAwB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE;IACpD,MAAM,cAAc,GAAG;QACrB,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE;KACtD,CAAC;IACF,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,QAAQ,EAAE,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,KAAK,EAC7B,UAAyB,EACzB,QAAmB,EACnB,MAAc,EACF,EAAE;IACd,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC;QAC9B,CAAC,EAAE,UAAU,CAAC,cAAc;QAC5B,CAAC,EAAE,QAAQ;QACX,CAAC,EAAE,MAAM;KACV,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAE3C,IAAI,UAAU;QAAE,OAAO,UAAe,CAAC;IAEvC,MAAM,gBAAgB,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,wBAAwB,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE;QAC5F,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;KACtB,CAAC,CAAC;IACH,IAAI,gBAAgB,EAAE;QACpB,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;QAC1C,OAAO,gBAAqB,CAAC;KAC9B;IAED,IAAI,YAAY,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE;QACjD,MAAM,mBAAmB,GAAG,MAAM,UAAU,CAAC,OAAO,CAClD,wBAAwB,CAAC,QAAQ,EAAE,YAAY,CAAC,EAChD;YACE,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;SACtB,CACF,CAAC;QACF,IAAI,mBAAmB,EAAE;YACvB,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;YAC7C,OAAO,mBAAwB,CAAC;SACjC;KACF;IAED,MAAM,SAAS,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE;QACnD,IAAI,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE;KACtB,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACnC,OAAO,SAAc,CAAC;AACxB,CAAC,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
@@ -1,3 +1,4 @@
1
+ export * as calculation from './calculation.js';
1
2
  export { default as findLocalizedText } from './find-localized-text.js';
2
3
  export * from './locale-helpers.js';
3
4
  export { default as objectInvert } from './object-invert.js';
@@ -1,3 +1,4 @@
1
+ export * as calculation from './calculation.js';
1
2
  export { default as findLocalizedText } from './find-localized-text.js';
2
3
  export * from './locale-helpers.js';
3
4
  export { default as objectInvert } from './object-invert.js';
@@ -1 +1 @@
1
- {"version":3,"file":"utils-index.js","sourceRoot":"","sources":["../src/utils-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACxE,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAExE;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC"}
1
+ {"version":3,"file":"utils-index.js","sourceRoot":"","sources":["../src/utils-index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAEhD,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AACxE,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAExE;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE7C;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/utils",
3
- "version": "2.2.3",
3
+ "version": "2.3.1",
4
4
  "main": "lib/utils-index.js",
5
5
  "exports": {
6
6
  ".": "./lib/utils-index.js",
@@ -30,18 +30,17 @@
30
30
  },
31
31
  "homepage": "https://github.com/unchainedshop/unchained#readme",
32
32
  "dependencies": {
33
- "@unchainedshop/logger": "^2.2.3",
33
+ "@unchainedshop/logger": "^2.3.1",
34
34
  "abort-controller": "3.0.0",
35
- "bson": "^4.7.2",
36
35
  "hashids": "^2.3.0",
37
- "jest": "^29.5.0",
36
+ "jest": "^29.6.1",
38
37
  "locale": "0.1.0",
39
- "lru-cache": "^7.14.1",
38
+ "lru-cache": "^10.0.0",
40
39
  "simpl-schema": "=3.2.0"
41
40
  },
42
41
  "devDependencies": {
43
- "@types/node": "^18.16.16",
44
- "@unchainedshop/types": "^2.2.3",
45
- "typescript": "^4.9.5"
42
+ "@types/node": "^18.16.19",
43
+ "@unchainedshop/types": "^2.3.1",
44
+ "typescript": "^5.1.6"
46
45
  }
47
46
  }
@@ -0,0 +1,275 @@
1
+ import { applyRate, resolveRatioAndTaxDivisorForPricingSheet, roundToNext, resolveAmountAndTax, applyDiscountToMultipleShares, calculateAmountToSplit } from "./calculation";
2
+
3
+ describe('roundToNext', () => {
4
+ it('rounds to the next multiple of precision correctly when the value is positive', () => {
5
+ expect(roundToNext(5, 2)).toBe(6);
6
+ expect(roundToNext(10, 5)).toBe(10);
7
+ expect(roundToNext(13, 5)).toBe(15);
8
+ });
9
+
10
+ it('rounds to the next multiple of precision correctly when the value is negative', () => {
11
+ expect(roundToNext(-5, 2)).toBe(-4);
12
+ expect(roundToNext(-10, 5)).toBe(-10);
13
+ expect(roundToNext(-13, 5)).toBe(-10);
14
+ });
15
+
16
+ it('returns 0 when the value is 0', () => {
17
+ expect(roundToNext(0, 5)).toBe(0);
18
+ });
19
+
20
+ it('returns the same value when the precision is 1', () => {
21
+ expect(roundToNext(5, 1)).toBe(5);
22
+ });
23
+
24
+ });
25
+
26
+ describe("resolveRatioAndTaxDivisorForPricingSheet", () => {
27
+ it('total is 0 and pricing is provided', () => {
28
+ const pricing = {
29
+ taxSum: () => 10,
30
+ gross: () => 20,
31
+ };
32
+ const result = resolveRatioAndTaxDivisorForPricingSheet(pricing, 0);
33
+ expect(result).toEqual({ ratio: 1, taxDivisor: 1 });
34
+ });
35
+
36
+ it('gross - tax is 0', () => {
37
+ const pricing = {
38
+ taxSum: () => 10,
39
+ gross: () => 10,
40
+ };
41
+ const result = resolveRatioAndTaxDivisorForPricingSheet(pricing, 20);
42
+ expect(result).toEqual({ ratio: 0, taxDivisor: 0 });
43
+ });
44
+
45
+ it('gross - tax is not 0', () => {
46
+ const pricing = {
47
+ taxSum: () => 10,
48
+ gross: () => 20,
49
+ };
50
+ const result = resolveRatioAndTaxDivisorForPricingSheet(pricing, 20);
51
+ expect(result).toEqual({ ratio: 1, taxDivisor: 2 });
52
+ });
53
+
54
+ it('taxSum is 0', () => {
55
+ const pricing = {
56
+ taxSum: () => 0,
57
+ gross: () => 20,
58
+ };
59
+ const result = resolveRatioAndTaxDivisorForPricingSheet(pricing, 20);
60
+ expect(result).toEqual({ ratio: 1, taxDivisor: 1 });
61
+ });
62
+
63
+ })
64
+
65
+
66
+ describe("resolveAmountAndTax", () => {
67
+ it('ratio is 0 and taxDivisor is 0', () => {
68
+ const result = resolveAmountAndTax({ ratio: 0, taxDivisor: 0 }, 100);
69
+ expect(result).toEqual([0, 0]);
70
+ });
71
+
72
+ it('ratio is not 0 and taxDivisor is 0', () => {
73
+ const result = resolveAmountAndTax({ ratio: 0.5, taxDivisor: 0 }, 100);
74
+ expect(result).toEqual([50, 0]);
75
+ });
76
+
77
+ it('ratio is 0 and taxDivisor is not 0', () => {
78
+ const result = resolveAmountAndTax({ ratio: 0, taxDivisor: 2 }, 100);
79
+ expect(result).toEqual([0, 0]);
80
+ });
81
+
82
+
83
+ it('ratio and taxDivisor are not 0', () => {
84
+ const result = resolveAmountAndTax({ ratio: 0.5, taxDivisor: 2 }, 100);
85
+ expect(result).toEqual([50, 25]);
86
+ });
87
+
88
+ it('ratio and taxDivisor are not finite number', () => {
89
+ const result = resolveAmountAndTax({ ratio: Number.NaN, taxDivisor: Number.NaN }, 100);
90
+ expect(result).toEqual([0, 0]);
91
+ });
92
+ })
93
+
94
+ describe("resolveAmountAndTax", () => {
95
+ it('shares are empty', () => {
96
+ const result = applyDiscountToMultipleShares([], 100);
97
+ expect(result).toEqual([0, 0]);
98
+ });
99
+
100
+ it('shares have one share', () => {
101
+ const shares = [{ ratio: 0.5, taxDivisor: 2 }];
102
+ const result = applyDiscountToMultipleShares(shares, 100);
103
+ expect(result).toEqual([50, 25]);
104
+ });
105
+
106
+ it('shares have multiple shares', () => {
107
+ const shares = [
108
+ { ratio: 0.5, taxDivisor: 2 },
109
+ { ratio: 0.2, taxDivisor: 1.5 },
110
+ ];
111
+ const result = applyDiscountToMultipleShares(shares, 100);
112
+ expect(result).toEqual([70, 31.666666666666664]);
113
+ });
114
+ })
115
+
116
+ describe('applyRate', () => {
117
+ it('applies the rate correctly when a rate is provided', () => {
118
+ const configuration = {
119
+ rate: 0.1
120
+ };
121
+ const amount = 100;
122
+ expect(applyRate(configuration, amount)).toBe(10);
123
+ });
124
+
125
+ it('applies the fixed rate correctly when a fixed rate is provided', () => {
126
+ const configuration = {
127
+ fixedRate: 50
128
+ };
129
+ const amount = 100;
130
+ expect(applyRate(configuration, amount)).toBe(50);
131
+ });
132
+
133
+ it('applies the fixed rate correctly when a fixed rate is provided and the amount is less than fixed rate', () => {
134
+ const configuration = {
135
+ fixedRate: 150
136
+ };
137
+ const amount = 100;
138
+ expect(applyRate(configuration, amount)).toBe(100);
139
+ });
140
+
141
+ it('applies the rate correctly when rate is less than or equal to 0', () => {
142
+ const configuration = {
143
+ rate: -0.1
144
+ };
145
+ const amount = 100;
146
+ expect(applyRate(configuration, amount)).toBe(-10);
147
+ });
148
+ it('applies the rate correctly when only rate is provided and amount is negative', () => {
149
+ const configuration = {
150
+ rate: 0.1
151
+ };
152
+ const amount = -100;
153
+ expect(applyRate(configuration, amount)).toBe(-10);
154
+ });
155
+
156
+
157
+ it('applies the rate correctly when only rate is provided and amount is negative', () => {
158
+ const configuration = {
159
+ rate: 0.1
160
+ };
161
+ const amount = -100;
162
+ expect(applyRate(configuration, amount)).toBe(-10);
163
+ });
164
+
165
+
166
+ it('applies the rate correctly when only rate is provided and amount is negative', () => {
167
+ const configuration = {
168
+ rate: 0.1
169
+ };
170
+ const amount = -100;
171
+ expect(applyRate(configuration, amount)).toBe(-10);
172
+ });
173
+
174
+
175
+
176
+ it('applies the rate correctly when only rate is provided and amount is negative', () => {
177
+ const configuration = {
178
+ rate: 0.1
179
+ };
180
+ const amount = -100;
181
+ expect(applyRate(configuration, amount)).toBe(-10);
182
+ });
183
+
184
+
185
+ it('returns 0 when rate and fixed rate are not provided', () => {
186
+ const configuration = {};
187
+ const amount = 100;
188
+ expect(applyRate(configuration, amount)).toBe(0);
189
+ });
190
+
191
+ it('applies the rate correctly when only rate is provided and amount is negative', () => {
192
+ const configuration = {
193
+ rate: 0.1
194
+ };
195
+ const amount = -100;
196
+ expect(applyRate(configuration, amount)).toBe(-10);
197
+ });
198
+
199
+ it('returns 0 when rate and fixed rate are not provided', () => {
200
+ const configuration = {};
201
+ const amount = 100;
202
+ expect(applyRate(configuration, amount)).toBe(0);
203
+ });
204
+
205
+
206
+ });
207
+
208
+
209
+ describe('calculateAmountToSplit', () => {
210
+ it('calculates the correct amount to split when using a rate', () => {
211
+ const configuration = {
212
+ rate: 0.1,
213
+ alreadyDeducted: 0,
214
+ };
215
+ const amount = 1000;
216
+ expect(calculateAmountToSplit(configuration, amount)).toBe(100);
217
+ });
218
+
219
+ it('calculates the correct amount to split when using a fixed rate', () => {
220
+ const configuration = {
221
+ fixedRate: 50,
222
+ alreadyDeducted: 0,
223
+ };
224
+ const amount = 1000;
225
+ expect(calculateAmountToSplit(configuration, amount)).toBe(50);
226
+ });
227
+
228
+ it('calculates the correct amount to split when alreadyDeducted is non-zero', () => {
229
+ const configuration = {
230
+ rate: 0.1,
231
+ alreadyDeducted: 10,
232
+ };
233
+ const amount = 1000;
234
+ expect(calculateAmountToSplit(configuration, amount)).toBe(90);
235
+ });
236
+
237
+ it('returns 0 when the amount to deduct is less than or equal to alreadyDeducted', () => {
238
+ const configuration = {
239
+ rate: 0.1,
240
+ alreadyDeducted: 100,
241
+ };
242
+ const amount = 1000;
243
+ expect(calculateAmountToSplit(configuration, amount)).toBe(0);
244
+ });
245
+
246
+ it('returns 0 when the amount is less than or equal to 0', () => {
247
+ const configuration = {
248
+ rate: 0.1,
249
+ alreadyDeducted: 0,
250
+ };
251
+ const amount = 0;
252
+ expect(calculateAmountToSplit(configuration, amount)).toBe(0);
253
+ });
254
+
255
+
256
+ it('returns 0 when amount is negative', () => {
257
+ const configuration = {
258
+ rate: 0.1,
259
+ alreadyDeducted: 0,
260
+ };
261
+ const amount = -1000;
262
+ expect(calculateAmountToSplit(configuration, amount)).toBe(0);
263
+ });
264
+
265
+ it('returns 0 when configuration rate is negative', () => {
266
+ const configuration = {
267
+ rate: -0.1,
268
+ alreadyDeducted: 0,
269
+ };
270
+ const amount = 1000;
271
+ expect(calculateAmountToSplit(configuration, amount)).toBe(0);
272
+ });
273
+
274
+
275
+ });
@@ -0,0 +1,62 @@
1
+ export type PricingInterface = { taxSum: () => number; gross: () => number };
2
+
3
+ export const roundToNext = (value: number, precision: number) =>
4
+ Math.ceil(value / precision) * precision;
5
+
6
+ export const resolveRatioAndTaxDivisorForPricingSheet = (pricing: PricingInterface, total: number) => {
7
+ if (total === 0 || !pricing) {
8
+ return {
9
+ ratio: 1,
10
+ taxDivisor: 1,
11
+ };
12
+ }
13
+ const tax = pricing.taxSum();
14
+ const gross = pricing.gross();
15
+ if (gross - tax === 0) {
16
+ return {
17
+ ratio: 0,
18
+ taxDivisor: 0,
19
+ };
20
+ }
21
+ return {
22
+ ratio: gross / total,
23
+ taxDivisor: gross / (gross - tax),
24
+ };
25
+ };
26
+
27
+ export const calculateAmountToSplit = (
28
+ configuration: { rate?: number; fixedRate?: number; alreadyDeducted?: number },
29
+ amount: number,
30
+ ) => {
31
+ const deductionAmount = configuration.rate
32
+ ? amount * configuration.rate
33
+ : Math.min(configuration.fixedRate, amount);
34
+
35
+ const leftInDiscount = Math.max(0, deductionAmount - (configuration.alreadyDeducted ?? 0));
36
+ return leftInDiscount;
37
+ };
38
+
39
+ export const applyRate = (configuration: { fixedRate?: number; rate?: number }, amount) => {
40
+ const { rate, fixedRate } = configuration;
41
+ return rate ? amount * rate : Math.min(fixedRate || 0, amount);
42
+ };
43
+
44
+ export const resolveAmountAndTax = (
45
+ { ratio, taxDivisor }: { ratio?: number; taxDivisor?: number },
46
+ amount: number,
47
+ ) => {
48
+ const shareAmount = Number.isFinite(ratio) ? amount * ratio : 0;
49
+ const shareTaxAmount =
50
+ Number.isFinite(taxDivisor) && taxDivisor !== 0 ? shareAmount - shareAmount / taxDivisor : 0;
51
+ return [shareAmount, shareTaxAmount];
52
+ };
53
+
54
+ export const applyDiscountToMultipleShares = (shares, amount) => {
55
+ return shares.reduce(
56
+ ([currentDiscountAmount, currentTaxAmount], share) => {
57
+ const [shareAmount, shareTaxAmount] = resolveAmountAndTax(share, amount);
58
+ return [currentDiscountAmount + shareAmount, currentTaxAmount + shareTaxAmount];
59
+ },
60
+ [0, 0],
61
+ );
62
+ };
@@ -1,5 +1,5 @@
1
1
  import 'abort-controller/polyfill.js';
2
- import LRU from 'lru-cache';
2
+ import { LRUCache } from 'lru-cache';
3
3
  import { Collection, Filter, Locale, Document } from '@unchainedshop/types/common.js';
4
4
  import { systemLocale } from './locale-helpers.js';
5
5
 
@@ -7,7 +7,7 @@ const { NODE_ENV } = process.env;
7
7
 
8
8
  const ttl = NODE_ENV === 'production' ? 1000 * 10 : 0; // 10 seconds or 0 seconds
9
9
 
10
- const textCache = new LRU({ max: 50000, ttl });
10
+ const textCache = new LRUCache({ max: 50000, ttl });
11
11
 
12
12
  const extendSelectorWithLocale = (selector, locale) => {
13
13
  const localeSelector = {
@@ -1,3 +1,5 @@
1
+ export * as calculation from './calculation.js';
2
+
1
3
  export { default as findLocalizedText } from './find-localized-text.js';
2
4
  export * from './locale-helpers.js';
3
5
  export { default as objectInvert } from './object-invert.js';
package/tsconfig.json CHANGED
@@ -5,7 +5,5 @@
5
5
  "outDir": "lib"
6
6
  },
7
7
  "exclude": ["**/*.test.ts", "**/*.test.js", "tests"],
8
- "include": [
9
- "./src"
10
- ]
11
- }
8
+ "include": ["./src"]
9
+ }