homeflowjs 1.0.61 → 1.0.63
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.
- package/package.json +1 -1
- package/properties/properties-display/properties-display.component.jsx +1 -1
- package/utils/stamp-duty-calculator/country-rates.js +53 -0
- package/utils/stamp-duty-calculator/english-rates.js +38 -62
- package/utils/stamp-duty-calculator/stamp-duty-calculator.js +8 -10
- package/utils/stamp-duty-calculator/stamp-duty-utils.js +21 -0
- package/utils/stamp-duty-calculator/scottish-rates.js +0 -104
- package/utils/stamp-duty-calculator/welsh-rates.js +0 -114
package/package.json
CHANGED
@@ -90,7 +90,7 @@ const PropertiesDisplay = ({
|
|
90
90
|
const propertiesLength = properties.length;
|
91
91
|
const propertiesInsertsMap = new Map();
|
92
92
|
|
93
|
-
inserts
|
93
|
+
inserts?.forEach((insert) => {
|
94
94
|
const property = properties[insert.index - 1] || properties[propertiesLength - 1];
|
95
95
|
propertiesInsertsMap.set(property.property_id, insert);
|
96
96
|
});
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import { calculateRange, getPriceBracketIndex } from "./stamp-duty-utils";
|
2
|
+
|
3
|
+
const countryRates = (price, firstTimeBuyer, additionalProperty, ukResident, country) => {
|
4
|
+
const countryConfig = {
|
5
|
+
'scotland': {
|
6
|
+
cmsData: Homeflow.get('stamp_duty_scotland'),
|
7
|
+
base: 'base_lbtt_rate',
|
8
|
+
},
|
9
|
+
'wales': {
|
10
|
+
cmsData: Homeflow.get('stamp_duty_wales'),
|
11
|
+
base: 'base_ltt_rate',
|
12
|
+
}
|
13
|
+
}
|
14
|
+
const cmsRates = countryConfig[country].cmsData;
|
15
|
+
|
16
|
+
const buyerStatusAsKeyOfObject = () => {
|
17
|
+
if(firstTimeBuyer) return 'first_time_buyer_rate';
|
18
|
+
if(additionalProperty) return 'additional_property_rate';
|
19
|
+
return countryConfig[country].base;
|
20
|
+
};
|
21
|
+
const bracketForPrice = +(cmsRates[getPriceBracketIndex(price, cmsRates)]['non_uk_resident_rate']);
|
22
|
+
|
23
|
+
const initalTotalRate = () => {
|
24
|
+
if (!ukResident && bracketForPrice) return +((price * (bracketForPrice / 100)).toFixed(2));
|
25
|
+
return 0;
|
26
|
+
}
|
27
|
+
|
28
|
+
const stampDutyRatesCalculation = cmsRates.reduce((accumulator, _, index) => {
|
29
|
+
const percentageFromList = +(cmsRates[index][buyerStatusAsKeyOfObject()]) / 100;
|
30
|
+
const minimumPropertyPrice = cmsRates[index]['minimum_property_price'] || Number.POSITIVE_INFINITY;
|
31
|
+
const maxisumPropertyPrice = cmsRates[index]['maximum_property_price'] || Number.POSITIVE_INFINITY;
|
32
|
+
const rateIndex = `rate${index + 1}`;
|
33
|
+
const rateForTheBracket = calculateRange(price, minimumPropertyPrice, maxisumPropertyPrice, percentageFromList);
|
34
|
+
|
35
|
+
accumulator[rateIndex] = rateForTheBracket;
|
36
|
+
accumulator.totalRate += rateForTheBracket;
|
37
|
+
|
38
|
+
accumulator.effectiveRate = (accumulator.totalRate / price) * 100;
|
39
|
+
|
40
|
+
return accumulator;
|
41
|
+
}, {
|
42
|
+
totalRate: initalTotalRate(),
|
43
|
+
effectiveRate: 0,
|
44
|
+
});
|
45
|
+
|
46
|
+
// Roundings
|
47
|
+
stampDutyRatesCalculation.effectiveRate = Math.round(stampDutyRatesCalculation.effectiveRate * 10) / 10;
|
48
|
+
stampDutyRatesCalculation.totalRate = Math.round(stampDutyRatesCalculation.totalRate);
|
49
|
+
|
50
|
+
return stampDutyRatesCalculation;
|
51
|
+
};
|
52
|
+
|
53
|
+
export default countryRates;
|
@@ -1,79 +1,55 @@
|
|
1
|
-
|
2
|
-
if (price <= lower) return 0;
|
3
|
-
return (Math.min(upper, price) - lower) * rate;
|
4
|
-
};
|
1
|
+
import { calculateRange, getPriceBracketIndex } from "./stamp-duty-utils";
|
5
2
|
|
6
3
|
const englishRates = (
|
7
|
-
price,
|
4
|
+
price = 0,
|
8
5
|
firstTimeBuyer,
|
9
6
|
additionalProperty,
|
10
7
|
ukResident = true, // Default to true if not explicitly specified
|
11
8
|
isCompany
|
12
9
|
) => {
|
13
|
-
|
14
|
-
|
15
|
-
return {
|
16
|
-
rate1: 0,
|
17
|
-
rate2: 0,
|
18
|
-
rate3: 0,
|
19
|
-
rate4: 0,
|
20
|
-
rate5: 0,
|
21
|
-
totalRate: 0,
|
22
|
-
effectiveRate: 0,
|
23
|
-
};
|
24
|
-
}
|
10
|
+
const englandRatesList = Homeflow.get('stamp_duty_england');
|
11
|
+
const bracketForPrice = +(englandRatesList[getPriceBracketIndex(price, englandRatesList)]['non_uk_resident_rate']);
|
25
12
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
let rate4 = 0;
|
32
|
-
let rate5 = 0;
|
13
|
+
const buyerStatusAsKeyOfObject = () => {
|
14
|
+
if(firstTimeBuyer) return 'first_time_buyer_rate';
|
15
|
+
if(additionalProperty) return 'additional_property_rate';
|
16
|
+
return 'base_sdlt_rate';
|
17
|
+
};
|
33
18
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
if
|
42
|
-
|
43
|
-
|
19
|
+
/**
|
20
|
+
* ATM the BE work doesn't have % for company purchases.
|
21
|
+
* Once that's done we can initiate the base object totalRate for:
|
22
|
+
* totalRate: (!ukResident && bracketForPrice) ? +((price * (bracketForPrice / 100)).toFixed(2)) : 0,
|
23
|
+
* But for now we need to have the 3 options + the hardcoded 17%
|
24
|
+
*/
|
25
|
+
const initalTotalRate = () => {
|
26
|
+
if(isCompany && price > 500_000) return price * 0.17;
|
27
|
+
if (!ukResident && bracketForPrice && !isCompany) return +((price * (bracketForPrice / 100)).toFixed(2));
|
28
|
+
return 0;
|
29
|
+
}
|
44
30
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
rate2 = calculateRange(price, 250000, 925000, 0.05);
|
54
|
-
rate3 = calculateRange(price, 925000, 1500000, 0.10);
|
55
|
-
rate4 = calculateRange(price, 1500000, Number.POSITIVE_INFINITY, 0.12);
|
56
|
-
}
|
31
|
+
const stampDutyRatesCalculation = englandRatesList.reduce((accumulator, _, index) => {
|
32
|
+
const percentageFromList = +(englandRatesList[index][buyerStatusAsKeyOfObject()]) / 100;
|
33
|
+
const minimumPropertyPrice = englandRatesList[index]['minimum_property_price'] || Number.POSITIVE_INFINITY;
|
34
|
+
const maxisumPropertyPrice = englandRatesList[index]['maximum_property_price'] || Number.POSITIVE_INFINITY;
|
35
|
+
const rateIndex = `rate${index + 1}`;
|
36
|
+
const rateForTheBracket = isCompany
|
37
|
+
? 0
|
38
|
+
: calculateRange(price, minimumPropertyPrice, maxisumPropertyPrice, percentageFromList);
|
57
39
|
|
58
|
-
|
40
|
+
accumulator[rateIndex] = rateForTheBracket;
|
41
|
+
accumulator.totalRate += rateForTheBracket;
|
59
42
|
|
60
|
-
|
61
|
-
if (!ukResident) {
|
62
|
-
totalRate += price * 0.02; // Non-UK resident surcharge
|
63
|
-
}
|
64
|
-
}
|
43
|
+
accumulator.effectiveRate = (accumulator.totalRate / price) * 100;
|
65
44
|
|
66
|
-
|
45
|
+
return accumulator;
|
46
|
+
}, {
|
47
|
+
// totalRate: (!ukResident && bracketForPrice) ? +((price * (bracketForPrice / 100)).toFixed(2)) : 0,
|
48
|
+
totalRate: initalTotalRate(),
|
49
|
+
effectiveRate: 0,
|
50
|
+
});
|
67
51
|
|
68
|
-
return
|
69
|
-
rate1,
|
70
|
-
rate2,
|
71
|
-
rate3,
|
72
|
-
rate4,
|
73
|
-
rate5,
|
74
|
-
totalRate,
|
75
|
-
effectiveRate,
|
76
|
-
};
|
52
|
+
return stampDutyRatesCalculation;
|
77
53
|
};
|
78
54
|
|
79
55
|
export default englishRates;
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import englishRates from './english-rates';
|
2
|
-
import
|
3
|
-
import welshRates from './welsh-rates';
|
2
|
+
import countryRates from './country-rates';
|
4
3
|
|
5
4
|
/**
|
6
5
|
* We already have a DefaultStampDutyCalculator component,
|
@@ -18,14 +17,13 @@ const stampDutyCalculator = ({
|
|
18
17
|
};
|
19
18
|
}
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
return welshRates(price, additionalProperty, ukResident);
|
20
|
+
/**
|
21
|
+
* For Scotland and Wales
|
22
|
+
* Once the BE brings data for companies (isCompany)
|
23
|
+
* countryRates will need an update and then we can have just one method.
|
24
|
+
*/
|
25
|
+
if (country === 'scotland' || country === 'wales') {
|
26
|
+
return countryRates(price, firstTimeBuyer, additionalProperty, ukResident, country);
|
29
27
|
}
|
30
28
|
|
31
29
|
// If country not is not specified use English rates by default
|
@@ -0,0 +1,21 @@
|
|
1
|
+
export const calculateRange = (price, lower, upper, rate) => {
|
2
|
+
if (price <= lower) return 0;
|
3
|
+
return Math.round(((Math.min(upper, price) - lower) * rate) * 10) / 10;
|
4
|
+
};
|
5
|
+
|
6
|
+
export const getPriceBracketIndex = (price, arr) => {
|
7
|
+
const lastIndex = arr.length - 1;
|
8
|
+
let bracketIndex = null;
|
9
|
+
|
10
|
+
if (price <= arr[0].maximum_property_price) return 0;
|
11
|
+
if (price >= arr[lastIndex].minimum_property_price) return lastIndex;
|
12
|
+
|
13
|
+
arr.forEach((rates, index) => {
|
14
|
+
if (
|
15
|
+
(rates.minimum_property_price || 0) <= price
|
16
|
+
&& (rates.minimum_property_price || Number.POSITIVE_INFINITY) > price
|
17
|
+
) bracketIndex = index;
|
18
|
+
});
|
19
|
+
|
20
|
+
return bracketIndex || 0;
|
21
|
+
}
|
@@ -1,104 +0,0 @@
|
|
1
|
-
const scottishRates = (price, firstTimeBuyer, additionalProperty, ukResident) => {
|
2
|
-
let effectiveRate = 0;
|
3
|
-
let totalRate = 0;
|
4
|
-
const rate1 = 0;
|
5
|
-
let rate2 = 0;
|
6
|
-
let rate3 = 0;
|
7
|
-
let rate4 = 0;
|
8
|
-
let rate5 = 0;
|
9
|
-
|
10
|
-
if (firstTimeBuyer) {
|
11
|
-
// Rate 2
|
12
|
-
if (price - 175000 > 0) {
|
13
|
-
if ((price - 175000) > (250000 - 175000)) {
|
14
|
-
rate2 = (250000 - 175000) * 0.02;
|
15
|
-
} else {
|
16
|
-
rate2 = (price - 175000) * 0.02;
|
17
|
-
}
|
18
|
-
}
|
19
|
-
|
20
|
-
// Rate 3
|
21
|
-
if (price - 250000 > 0) {
|
22
|
-
if ((price - 250000) > (325000 - 250000)) {
|
23
|
-
rate3 = (325000 - 250000) * 0.05;
|
24
|
-
} else {
|
25
|
-
rate3 = (price - 250000) * 0.05;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
|
29
|
-
// Rate 4
|
30
|
-
if (price - 325000 > 0) {
|
31
|
-
if ((price - 325000) > (750000 - 325000)) {
|
32
|
-
rate4 = (750000 - 325000) * 0.10;
|
33
|
-
} else {
|
34
|
-
rate4 = (price - 325000) * 0.10;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
// Rate 5
|
39
|
-
if (price - 750000 > 0) {
|
40
|
-
rate5 = (price - 750000);
|
41
|
-
rate5 *= 0.12;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
if (!firstTimeBuyer) {
|
46
|
-
// Rate 2
|
47
|
-
if (price - 145000 > 0) {
|
48
|
-
if ((price - 145000) > (250000 - 145000)) {
|
49
|
-
rate2 = (250000 - 145000) * 0.02;
|
50
|
-
} else {
|
51
|
-
rate2 = (price - 145000) * 0.02;
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
// Rate 3
|
56
|
-
if (price - 250000 > 0) {
|
57
|
-
if ((price - 250000) > (325000 - 250000)) {
|
58
|
-
rate3 = (325000 - 250000) * 0.05;
|
59
|
-
} else {
|
60
|
-
rate3 = (price - 250000) * 0.05;
|
61
|
-
}
|
62
|
-
}
|
63
|
-
|
64
|
-
// Rate 4
|
65
|
-
if (price - 325000 > 0) {
|
66
|
-
if ((price - 325000) > (750000 - 325000)) {
|
67
|
-
rate4 = (750000 - 325000) * 0.10;
|
68
|
-
} else {
|
69
|
-
rate4 = (price - 325000) * 0.10;
|
70
|
-
}
|
71
|
-
}
|
72
|
-
|
73
|
-
// Rate 5
|
74
|
-
if (price - 750000 > 0) {
|
75
|
-
rate5 = (price - 750000);
|
76
|
-
rate5 *= 0.12;
|
77
|
-
}
|
78
|
-
}
|
79
|
-
|
80
|
-
totalRate = rate1 + rate2 + rate3 + rate4 + rate5;
|
81
|
-
effectiveRate = totalRate / price;
|
82
|
-
if (!ukResident) {
|
83
|
-
totalRate = totalRate * (effectiveRate + 0.02) / effectiveRate;
|
84
|
-
effectiveRate += 0.02;
|
85
|
-
}
|
86
|
-
effectiveRate *= 100;
|
87
|
-
|
88
|
-
if (additionalProperty) {
|
89
|
-
const ADS = price * 0.06;
|
90
|
-
totalRate += ADS;
|
91
|
-
}
|
92
|
-
|
93
|
-
return {
|
94
|
-
rate1,
|
95
|
-
rate2,
|
96
|
-
rate3,
|
97
|
-
rate4,
|
98
|
-
rate5,
|
99
|
-
totalRate,
|
100
|
-
effectiveRate: Math.round(effectiveRate * 10) / 10,
|
101
|
-
};
|
102
|
-
};
|
103
|
-
|
104
|
-
export default scottishRates;
|
@@ -1,114 +0,0 @@
|
|
1
|
-
const welshRates = (price, additionalProperty, ukResident) => {
|
2
|
-
let effectiveRate = 0;
|
3
|
-
let totalRate = 0;
|
4
|
-
let rate1 = 0;
|
5
|
-
let rate2 = 0;
|
6
|
-
let rate3 = 0;
|
7
|
-
let rate4 = 0;
|
8
|
-
let rate5 = 0;
|
9
|
-
let rate6 = 0;
|
10
|
-
|
11
|
-
if (additionalProperty) {
|
12
|
-
// Rate 1
|
13
|
-
if (price > 180000) rate1 = 180000 * 0.05;
|
14
|
-
if (price <= 180000) {
|
15
|
-
rate1 = price * 0.05;
|
16
|
-
}
|
17
|
-
|
18
|
-
// Rate 2
|
19
|
-
if (price - 180000 > 0) {
|
20
|
-
if ((price - 180000) > (250000 - 180000)) {
|
21
|
-
rate2 = (250000 - 180000) * 0.085;
|
22
|
-
} else {
|
23
|
-
rate2 = (price - 180000) * 0.085;
|
24
|
-
}
|
25
|
-
}
|
26
|
-
|
27
|
-
// Rate 3
|
28
|
-
if (price - 250000 > 0) {
|
29
|
-
if ((price - 250000) > (400000 - 250000)) {
|
30
|
-
rate3 = (400000 - 250000) * 0.10;
|
31
|
-
} else {
|
32
|
-
rate3 = (price - 250000) * 0.10;
|
33
|
-
}
|
34
|
-
}
|
35
|
-
|
36
|
-
// Rate 4
|
37
|
-
if (price - 400000 > 0) {
|
38
|
-
if ((price - 400000) > (750000 - 400000)) {
|
39
|
-
rate4 = (750000 - 400000) * 0.125;
|
40
|
-
} else {
|
41
|
-
rate4 = (price - 400000) * 0.125;
|
42
|
-
}
|
43
|
-
}
|
44
|
-
|
45
|
-
// Rate 5
|
46
|
-
if (price - 750000 > 0) {
|
47
|
-
if ((price - 750000) > (1500000 - 750000)) {
|
48
|
-
rate5 = (1500000 - 750000) * 0.15;
|
49
|
-
} else {
|
50
|
-
rate5 = (price - 750000) * 0.15;
|
51
|
-
}
|
52
|
-
}
|
53
|
-
|
54
|
-
// Rate 6
|
55
|
-
if (price - 1500000 > 0) {
|
56
|
-
rate6 = (price - 1500000) * 0.17;
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
if (!additionalProperty) {
|
61
|
-
// Rate 2
|
62
|
-
if (price - 225000 > 0) {
|
63
|
-
if ((price - 225000) > (400000 - 225000)) {
|
64
|
-
rate2 = (400000 - 225000) * 0.06;
|
65
|
-
} else {
|
66
|
-
rate2 = (price - 225000) * 0.06;
|
67
|
-
}
|
68
|
-
}
|
69
|
-
|
70
|
-
// Rate 3
|
71
|
-
if (price - 400000 > 0) {
|
72
|
-
if ((price - 400000) > (750000 - 400000)) {
|
73
|
-
rate3 = (750000 - 400000) * 0.075;
|
74
|
-
} else {
|
75
|
-
rate3 = (price - 400000) * 0.075;
|
76
|
-
}
|
77
|
-
}
|
78
|
-
|
79
|
-
// Rate 4
|
80
|
-
if (price - 750000 > 0) {
|
81
|
-
if ((price - 750000) > (1500000 - 750000)) {
|
82
|
-
rate4 = (1500000 - 750000) * 0.10;
|
83
|
-
} else {
|
84
|
-
rate4 = (price - 750000) * 0.10;
|
85
|
-
}
|
86
|
-
}
|
87
|
-
|
88
|
-
// Rate 5
|
89
|
-
if (price - 1500000 > 0) {
|
90
|
-
rate5 = (price - 1500000) * 0.12;
|
91
|
-
}
|
92
|
-
}
|
93
|
-
|
94
|
-
totalRate = rate1 + rate2 + rate3 + rate4 + rate5 + rate6;
|
95
|
-
effectiveRate = totalRate / price;
|
96
|
-
if (!ukResident) {
|
97
|
-
totalRate = totalRate * (effectiveRate + 0.02) / effectiveRate;
|
98
|
-
effectiveRate += 0.02;
|
99
|
-
}
|
100
|
-
effectiveRate *= 100;
|
101
|
-
|
102
|
-
return {
|
103
|
-
rate1,
|
104
|
-
rate2,
|
105
|
-
rate3,
|
106
|
-
rate4,
|
107
|
-
rate5,
|
108
|
-
rate6,
|
109
|
-
totalRate,
|
110
|
-
effectiveRate: Math.round(effectiveRate * 10) / 10,
|
111
|
-
};
|
112
|
-
};
|
113
|
-
|
114
|
-
export default welshRates;
|