homeflowjs 1.0.67 → 1.0.69
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/stamp-duty-calculator/default-calculator.component.jsx +95 -169
- package/properties/stamp-duty-calculator/stamp-duty-calculator.component.jsx +21 -11
- package/utils/stamp-duty-calculator/english-rates.js +32 -25
- package/utils/stamp-duty-calculator/scotand-rates.js +48 -0
- package/utils/stamp-duty-calculator/stamp-duty-calculator.js +9 -11
- package/utils/stamp-duty-calculator/stamp-duty-utils.js +3 -3
- package/utils/stamp-duty-calculator/wales-rates.js +41 -0
- package/utils/stamp-duty-calculator/country-rates.js +0 -49
package/package.json
CHANGED
@@ -4,65 +4,61 @@ import englishRates from '../../utils/stamp-duty-calculator/english-rates';
|
|
4
4
|
|
5
5
|
import './stamp-duty-calculator.styles.scss';
|
6
6
|
|
7
|
-
const DefaultCalculator = ({
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
const
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
7
|
+
const DefaultCalculator = ({
|
8
|
+
purchasePrice,
|
9
|
+
setPurchasePrice,
|
10
|
+
firstTimeBuyer,
|
11
|
+
additionalProperty,
|
12
|
+
ukResident,
|
13
|
+
buyToLet
|
14
|
+
}) => {
|
15
|
+
const [priceDisplay, setPriceDisplay] = useState(purchasePrice);
|
16
|
+
const results = englishRates(
|
17
|
+
purchasePrice,
|
18
|
+
(firstTimeBuyer && !buyToLet),
|
19
|
+
(additionalProperty || buyToLet),
|
20
|
+
ukResident,
|
21
|
+
);
|
22
|
+
|
23
|
+
const englandRatesList = Homeflow.get('stamp_duty_england');
|
24
|
+
|
25
|
+
const ratesToCalculateBasedOnTaxType = () => {
|
26
|
+
const baseRates = englandRatesList['base'];
|
27
|
+
const firstTimeBuyerRates = englandRatesList['first_time_buyer'];
|
28
|
+
|
29
|
+
if (firstTimeBuyer && !buyToLet) {
|
30
|
+
const priceLimit = firstTimeBuyerRates[firstTimeBuyerRates?.length - 1]
|
31
|
+
?.['maximum_property_price'];
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
rate5,
|
39
|
-
effectiveRate,
|
40
|
-
totalRate
|
41
|
-
} = results;
|
42
|
-
|
43
|
-
setRate1(rate1);
|
44
|
-
setRate2(rate2);
|
45
|
-
setRate3(rate3);
|
46
|
-
setRate4(rate4);
|
47
|
-
setRate5(rate5);
|
48
|
-
setTotalRate(totalRate);
|
49
|
-
setEffectiveRate(Math.round(effectiveRate * 10) / 10);
|
50
|
-
|
51
|
-
return null;
|
52
|
-
};
|
53
|
-
|
54
|
-
useEffect(() => {
|
55
|
-
if (property && property.price_value) {
|
56
|
-
setPurchasePrice(property.price_value);
|
57
|
-
calculateStampDuty(property.price_value);
|
33
|
+
if (priceLimit && purchasePrice > priceLimit) {
|
34
|
+
return baseRates;
|
35
|
+
} else {
|
36
|
+
return firstTimeBuyerRates;
|
37
|
+
}
|
58
38
|
}
|
59
|
-
}, [firstTimeBuyer, additionalProperty]);
|
60
39
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
40
|
+
return baseRates;
|
41
|
+
}
|
42
|
+
|
43
|
+
const ratesList = ratesToCalculateBasedOnTaxType();
|
44
|
+
|
45
|
+
const handleInputUpdate = (val) => {
|
46
|
+
let transformValues = val;
|
47
|
+
|
48
|
+
// Only accept numbers
|
49
|
+
if(transformValues.toUpperCase() != transformValues.toLowerCase()) return;
|
50
|
+
|
51
|
+
// If errors, default to 0
|
52
|
+
if (transformValues === NaN) transformValues = 0;
|
53
|
+
|
54
|
+
// Hacky way to keep the £ and multiple , in the input box while ultimately passing a number
|
55
|
+
if (transformValues?.includes('£')) transformValues = transformValues.replace('£', '');
|
56
|
+
if (transformValues?.includes(',')) transformValues = transformValues.replaceAll(',', '');
|
57
|
+
|
58
|
+
transformValues = +transformValues;
|
59
|
+
|
60
|
+
setPriceDisplay(transformValues);
|
61
|
+
}
|
66
62
|
|
67
63
|
return (
|
68
64
|
<div id="stampResi" className="stamp-duty-calculator main">
|
@@ -72,8 +68,8 @@ const DefaultCalculator = ({ purchasePrice, setPurchasePrice, firstTimeBuyer, ad
|
|
72
68
|
className="SD_money residential auto"
|
73
69
|
type="text"
|
74
70
|
placeholder="Purchase price"
|
75
|
-
value={`£${
|
76
|
-
onChange={
|
71
|
+
value={`£${priceDisplay?.toLocaleString() || '0'}`}
|
72
|
+
onChange={e => handleInputUpdate(e.target.value)}
|
77
73
|
/>
|
78
74
|
</div>
|
79
75
|
|
@@ -82,7 +78,7 @@ const DefaultCalculator = ({ purchasePrice, setPurchasePrice, firstTimeBuyer, ad
|
|
82
78
|
type="button"
|
83
79
|
className="SD_calculate btn residential"
|
84
80
|
data-preselector=".main"
|
85
|
-
onClick={() =>
|
81
|
+
onClick={() => setPurchasePrice(priceDisplay)}
|
86
82
|
>
|
87
83
|
Calculate
|
88
84
|
</button>
|
@@ -95,135 +91,65 @@ const DefaultCalculator = ({ purchasePrice, setPurchasePrice, firstTimeBuyer, ad
|
|
95
91
|
{' '}
|
96
92
|
<span className="SD_result residential">
|
97
93
|
£
|
98
|
-
{Number(totalRate).toLocaleString()}
|
94
|
+
{Number(results?.totalRate || 0).toLocaleString()}
|
99
95
|
</span>
|
100
96
|
{' '}
|
101
97
|
Stamp duty
|
102
98
|
</p>
|
103
99
|
|
104
|
-
{(firstTimeBuyer && property.price_value >= 625000) && (
|
105
|
-
<p id="first_time_buyer_info">First time buyers purchasing property for more than £625,000 will not be entitled to any relief and will pay SDLT at the standard rates.</p>
|
106
|
-
)}
|
107
|
-
|
108
100
|
<div className="results-table-wrap">
|
109
101
|
<p><strong>How this was calculated:</strong></p>
|
110
|
-
|
111
|
-
<table className="SD_results_table residential">
|
102
|
+
<table className="SD_results_table residential">
|
112
103
|
<thead>
|
113
104
|
<tr>
|
114
105
|
<th>Band</th>
|
115
|
-
<th>Stamp Duty Rate</th>
|
106
|
+
<th>{`${!buyToLet ? 'Stamp Duty ' : ''}Rate`}</th>
|
107
|
+
{(additionalProperty && !firstTimeBuyer && !buyToLet) && (
|
108
|
+
<th>Additional Property Rate</th>
|
109
|
+
)}
|
116
110
|
<th>Due</th>
|
117
111
|
</tr>
|
118
112
|
</thead>
|
119
113
|
<tbody>
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
114
|
+
{ratesList?.map((rate, index) => {
|
115
|
+
// long string builder
|
116
|
+
let titleForRate = `${rate?.maximum_property_price ? 'Between' : 'Over'}`;
|
117
|
+
titleForRate += ' ';
|
118
|
+
titleForRate += `£${(+rate?.minimum_property_price).toLocaleString()}`;
|
119
|
+
titleForRate += `${rate?.maximum_property_price ? ' and £' : ''}`;
|
120
|
+
titleForRate += `${(+rate?.maximum_property_price).toLocaleString() || ''}`;
|
121
|
+
|
122
|
+
return (
|
123
|
+
<tr key={rate.id}>
|
124
|
+
<td>
|
125
|
+
{titleForRate}
|
126
|
+
</td>
|
127
|
+
{buyToLet ? (
|
128
|
+
<td>
|
129
|
+
{`${(+rate?.base_sdlt_rate || 0) + (+rate?.additional_property_surcharge || 0)}%`}
|
130
|
+
</td>
|
131
|
+
) : (
|
132
|
+
<td>
|
133
|
+
{`${rate?.base_sdlt_rate || 0}%`}
|
134
|
+
</td>
|
135
|
+
)}
|
136
|
+
{(additionalProperty && !firstTimeBuyer && !buyToLet) && (
|
137
|
+
<td className="additional_rate">
|
138
|
+
{`${+rate?.additional_property_surcharge}%`}
|
139
|
+
</td>
|
140
|
+
)}
|
141
|
+
<td className="rate1">
|
142
|
+
{`£${Number(results?.[`rate${index + 1}`]).toLocaleString()}`}
|
143
|
+
</td>
|
144
|
+
</tr>
|
145
|
+
);
|
146
|
+
})}
|
147
147
|
</tbody>
|
148
148
|
</table>
|
149
|
-
) : (
|
150
|
-
<table className="SD_results_table residential">
|
151
|
-
<thead>
|
152
|
-
<tr>
|
153
|
-
<th>Band</th>
|
154
|
-
<th>Stamp Duty Rate</th>
|
155
|
-
<th>Additional Property Rate</th>
|
156
|
-
<th>Due</th>
|
157
|
-
</tr>
|
158
|
-
</thead>
|
159
|
-
<tbody>
|
160
|
-
<tr>
|
161
|
-
<td>Between £0 and £250,000</td>
|
162
|
-
<td> 0% </td>
|
163
|
-
<td className='additional_rate'> 3% </td>
|
164
|
-
<td className="rate1">
|
165
|
-
£
|
166
|
-
{Number(rate1).toLocaleString()}
|
167
|
-
</td>
|
168
|
-
</tr>
|
169
|
-
{/* <tr>
|
170
|
-
<td>Between £125,000 and £250,000</td>
|
171
|
-
<td> 2% </td>
|
172
|
-
<td className="rate2">
|
173
|
-
£
|
174
|
-
{Number(rate2).toLocaleString()}
|
175
|
-
</td>
|
176
|
-
</tr> */}
|
177
|
-
<tr>
|
178
|
-
<td>Between £250,001 and £925,000</td>
|
179
|
-
<td> 5% </td>
|
180
|
-
<td className='additional_rate'> 8% </td>
|
181
|
-
<td className="rate3">
|
182
|
-
£
|
183
|
-
{Number(rate2).toLocaleString()}
|
184
|
-
</td>
|
185
|
-
</tr>
|
186
|
-
<tr>
|
187
|
-
<td>Between £925,000 and £1,500,000 </td>
|
188
|
-
<td> 10% </td>
|
189
|
-
<td className='additional_rate'> 13% </td>
|
190
|
-
<td className="rate4">
|
191
|
-
£
|
192
|
-
{Number(rate3).toLocaleString()}
|
193
|
-
</td>
|
194
|
-
</tr>
|
195
|
-
<tr>
|
196
|
-
<td>Over £1,500,000 </td>
|
197
|
-
<td> 12% </td>
|
198
|
-
<td className='additional_rate'> 15% </td>
|
199
|
-
<td className="rate5">
|
200
|
-
£
|
201
|
-
{Number(rate4).toLocaleString()}
|
202
|
-
</td>
|
203
|
-
</tr>
|
204
|
-
<tr className="totals">
|
205
|
-
<td>Total</td>
|
206
|
-
<td className="effectiveRate">
|
207
|
-
{effectiveRate}
|
208
|
-
%
|
209
|
-
</td>
|
210
|
-
<td></td>
|
211
|
-
<td className="totalRate">
|
212
|
-
£
|
213
|
-
{Number(totalRate).toLocaleString()}
|
214
|
-
</td>
|
215
|
-
</tr>
|
216
|
-
</tbody>
|
217
|
-
</table>
|
218
|
-
)}
|
219
149
|
</div>
|
220
150
|
</div>
|
221
151
|
</div>
|
222
152
|
);
|
223
153
|
};
|
224
154
|
|
225
|
-
|
226
|
-
themePreferences: state.app.themePreferences,
|
227
|
-
});
|
228
|
-
|
229
|
-
export default connect(mapStateToProps)(DefaultCalculator);
|
155
|
+
export default DefaultCalculator;
|
@@ -1,14 +1,16 @@
|
|
1
1
|
import React, { useState } from 'react';
|
2
|
-
import { connect } from 'react-redux';
|
3
2
|
import DefaultCalculator from './default-calculator.component';
|
4
|
-
import BTLCalculator from './btl-calculator.component';
|
5
3
|
|
6
4
|
import './stamp-duty-calculator.styles.scss';
|
7
5
|
|
8
|
-
const StampDutyCalculator = (
|
6
|
+
const StampDutyCalculator = () => {
|
7
|
+
const property = Homeflow.get('property');
|
9
8
|
const [type, setType] = useState('residential');
|
9
|
+
const placeholderValue = 250_000;
|
10
|
+
const [purchasePrice, setPurchasePrice] = useState(
|
11
|
+
(property && property?.price_value) ? property.price_value : placeholderValue
|
12
|
+
);
|
10
13
|
const [purchaseType, setPurchaseType] = useState('firstTimeBuyer')
|
11
|
-
const [purchasePrice, setPurchasePrice] = useState();
|
12
14
|
const [firstTimeBuyer, setFirstTimeBuyer] = useState(false);
|
13
15
|
const [additionalProperty, setAdditionalProperty] = useState(false);
|
14
16
|
|
@@ -21,6 +23,7 @@ const StampDutyCalculator = ({ scotland, themePreferences }) => {
|
|
21
23
|
firstTimeBuyer={firstTimeBuyer}
|
22
24
|
additionalProperty={additionalProperty}
|
23
25
|
ukResident
|
26
|
+
buyToLet={type === 'btl'}
|
24
27
|
/>
|
25
28
|
);
|
26
29
|
}
|
@@ -55,7 +58,11 @@ const StampDutyCalculator = ({ scotland, themePreferences }) => {
|
|
55
58
|
<button
|
56
59
|
type="button"
|
57
60
|
className={`stamp-duty-cal__type ${type === 'btl' ? 'selected' : ''}`}
|
58
|
-
onClick={() =>
|
61
|
+
onClick={() => {
|
62
|
+
if (firstTimeBuyer) setFirstTimeBuyer(prev => !prev);
|
63
|
+
if (additionalProperty) setAdditionalProperty(prev => !prev);
|
64
|
+
setType('btl');
|
65
|
+
}}
|
59
66
|
>
|
60
67
|
Buy to Let
|
61
68
|
</button>
|
@@ -81,13 +88,16 @@ const StampDutyCalculator = ({ scotland, themePreferences }) => {
|
|
81
88
|
<label htmlFor="additionalProperty">Additional Property</label>
|
82
89
|
</div>
|
83
90
|
</div>
|
84
|
-
|
91
|
+
<DefaultCalculator
|
92
|
+
purchasePrice={purchasePrice}
|
93
|
+
setPurchasePrice={setPurchasePrice}
|
94
|
+
firstTimeBuyer={firstTimeBuyer}
|
95
|
+
additionalProperty={additionalProperty}
|
96
|
+
ukResident
|
97
|
+
buyToLet={type === 'btl'}
|
98
|
+
/>
|
85
99
|
</div>
|
86
100
|
);
|
87
101
|
};
|
88
102
|
|
89
|
-
|
90
|
-
themePreferences: state.app.themePreferences,
|
91
|
-
});
|
92
|
-
|
93
|
-
export default connect(mapStateToProps)(StampDutyCalculator);
|
103
|
+
export default StampDutyCalculator;
|
@@ -9,40 +9,47 @@ const englishRates = (
|
|
9
9
|
) => {
|
10
10
|
const englandRatesList = Homeflow.get('stamp_duty_england');
|
11
11
|
|
12
|
-
const
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
12
|
+
const ratesToCalculateBasedOnTaxType = () => {
|
13
|
+
const baseRates = englandRatesList['base'];
|
14
|
+
const firstTimeBuyerRates = englandRatesList['first_time_buyer'];
|
15
|
+
|
16
|
+
if (firstTimeBuyer) {
|
17
|
+
const priceLimit = firstTimeBuyerRates[firstTimeBuyerRates?.length - 1]
|
18
|
+
?.['maximum_property_price'];
|
19
|
+
|
20
|
+
if (priceLimit && price > priceLimit) {
|
21
|
+
return baseRates;
|
22
|
+
} else {
|
23
|
+
return firstTimeBuyerRates;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
return baseRates;
|
27
28
|
}
|
28
29
|
|
29
|
-
const
|
30
|
+
const ratesList = ratesToCalculateBasedOnTaxType();
|
31
|
+
|
32
|
+
const stampDutyRatesCalculation = ratesList.reduce((accumulator, _, index) => {
|
30
33
|
// Minumun price from the 1st braket should be always 0
|
31
34
|
const minimunFallback = index === 0 ? 0 : Number.POSITIVE_INFINITY;
|
32
|
-
const minimumPropertyPrice =
|
33
|
-
const
|
35
|
+
const minimumPropertyPrice = ratesList[index]['minimum_property_price'] || minimunFallback;
|
36
|
+
const maximumPropertyPrice = ratesList[index]['maximum_property_price'] || Number.POSITIVE_INFINITY;
|
34
37
|
const rateIndex = `rate${index + 1}`;
|
35
|
-
let percentageFromList = +(
|
38
|
+
let percentageFromList = +(ratesList[index]['base_sdlt_rate']) / 100;
|
39
|
+
|
40
|
+
if (!ukResident && ratesList[index]?.['non_uk_resident_surcharge']) {
|
41
|
+
percentageFromList += (+(ratesList[index]?.['non_uk_resident_surcharge']) / 100);
|
42
|
+
}
|
36
43
|
|
37
|
-
if (
|
38
|
-
percentageFromList += (+(
|
44
|
+
if ((additionalProperty || isCompany) && ratesList[index]?.['additional_property_surcharge']) {
|
45
|
+
percentageFromList += (+(ratesList[index]?.['additional_property_surcharge']) / 100);
|
39
46
|
}
|
40
47
|
|
41
48
|
percentageFromList = parseFloat(percentageFromList.toFixed(3));
|
42
49
|
|
43
|
-
const rateForTheBracket =
|
44
|
-
|
45
|
-
|
50
|
+
const rateForTheBracket = calculateRange(
|
51
|
+
price, minimumPropertyPrice, maximumPropertyPrice, percentageFromList,
|
52
|
+
);
|
46
53
|
|
47
54
|
accumulator[rateIndex] = rateForTheBracket;
|
48
55
|
accumulator.totalRate += rateForTheBracket;
|
@@ -51,7 +58,7 @@ const englishRates = (
|
|
51
58
|
|
52
59
|
return accumulator;
|
53
60
|
}, {
|
54
|
-
totalRate:
|
61
|
+
totalRate: 0,
|
55
62
|
effectiveRate: 0,
|
56
63
|
});
|
57
64
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { calculateRange, getPriceBracketIndex } from "./stamp-duty-utils";
|
2
|
+
|
3
|
+
const scotlandRates = (price, firstTimeBuyer, additionalProperty, isCompany) => {
|
4
|
+
const scotlandRatesList = Homeflow.get('stamp_duty_scotland');
|
5
|
+
|
6
|
+
const ratesToCalculateBasedOnTaxType = () => {
|
7
|
+
if(firstTimeBuyer) return scotlandRatesList['first_time_buyer'];
|
8
|
+
return scotlandRatesList['base'];
|
9
|
+
};
|
10
|
+
|
11
|
+
const ratesList = ratesToCalculateBasedOnTaxType();
|
12
|
+
|
13
|
+
const stampDutyRatesCalculation = ratesList.reduce((accumulator, _, index) => {
|
14
|
+
// Minumun price from the 1st braket should be always 0
|
15
|
+
const minimunFallback = index === 0 ? 0 : Number.POSITIVE_INFINITY;
|
16
|
+
const percentageFromList = +(ratesList[index]['base_lbtt_rate']) / 100;
|
17
|
+
const minimumPropertyPrice = ratesList[index]['minimum_property_price'] || minimunFallback;
|
18
|
+
const maximumPropertyPrice = ratesList[index]['maximum_property_price'] || Number.POSITIVE_INFINITY;
|
19
|
+
const rateIndex = `rate${index + 1}`;
|
20
|
+
const rateForTheBracket = calculateRange(price, minimumPropertyPrice, maximumPropertyPrice, percentageFromList);
|
21
|
+
|
22
|
+
accumulator[rateIndex] = rateForTheBracket;
|
23
|
+
accumulator.totalRate += rateForTheBracket;
|
24
|
+
|
25
|
+
accumulator.effectiveRate = (accumulator.totalRate / price) * 100;
|
26
|
+
|
27
|
+
return accumulator;
|
28
|
+
}, {
|
29
|
+
totalRate: 0,
|
30
|
+
effectiveRate: 0,
|
31
|
+
});
|
32
|
+
|
33
|
+
if (additionalProperty || isCompany) {
|
34
|
+
const additionalDwellingSurcharge = ratesList[getPriceBracketIndex(price, ratesList)]
|
35
|
+
?.['additional_property_surcharge'];
|
36
|
+
if (additionalDwellingSurcharge) {
|
37
|
+
stampDutyRatesCalculation.totalRate += ((price * additionalDwellingSurcharge) / 100);
|
38
|
+
};
|
39
|
+
}
|
40
|
+
|
41
|
+
// Roundings
|
42
|
+
stampDutyRatesCalculation.effectiveRate = Math.round(stampDutyRatesCalculation.effectiveRate * 10) / 10;
|
43
|
+
stampDutyRatesCalculation.totalRate = Math.round(stampDutyRatesCalculation.totalRate);
|
44
|
+
|
45
|
+
return stampDutyRatesCalculation;
|
46
|
+
};
|
47
|
+
|
48
|
+
export default scotlandRates;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import englishRates from './english-rates';
|
2
|
-
import
|
2
|
+
import walesRates from './wales-rates';
|
3
|
+
import scotlandRates from './scotand-rates';
|
3
4
|
|
4
5
|
/**
|
5
6
|
* We already have a DefaultStampDutyCalculator component,
|
@@ -17,16 +18,13 @@ const stampDutyCalculator = ({
|
|
17
18
|
};
|
18
19
|
}
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if (
|
26
|
-
|
27
|
-
|| country?.toLowerCase() === 'wales')
|
28
|
-
{
|
29
|
-
return countryRates(price, firstTimeBuyer, additionalProperty, ukResident, country);
|
21
|
+
if (country?.toLowerCase() === 'scotland') {
|
22
|
+
return scotlandRates(price, firstTimeBuyer, additionalProperty, isCompany);
|
23
|
+
};
|
24
|
+
|
25
|
+
|
26
|
+
if (country?.toLowerCase() === 'wales') {
|
27
|
+
return walesRates(price, additionalProperty, isCompany);
|
30
28
|
}
|
31
29
|
|
32
30
|
// If country not is not specified use English rates by default
|
@@ -12,10 +12,10 @@ export const getPriceBracketIndex = (price, arr) => {
|
|
12
12
|
|
13
13
|
arr.forEach((rates, index) => {
|
14
14
|
if (
|
15
|
-
(+(rates.maximum_property_price) || Number.POSITIVE_INFINITY)
|
16
|
-
&& +(rates.minimum_property_price)
|
15
|
+
(+(rates.maximum_property_price) || Number.POSITIVE_INFINITY) >= price
|
16
|
+
&& +(rates.minimum_property_price) <= price
|
17
17
|
) bracketIndex = index;
|
18
18
|
});
|
19
19
|
|
20
|
-
return bracketIndex
|
20
|
+
return bracketIndex;
|
21
21
|
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import { calculateRange } from "./stamp-duty-utils";
|
2
|
+
|
3
|
+
const walesRates = (price, additionalProperty, isCompany) => {
|
4
|
+
const walesRatesList = Homeflow.get('stamp_duty_wales');
|
5
|
+
|
6
|
+
const ratesToCalculateBasedOnTaxType = () => {
|
7
|
+
if(additionalProperty || isCompany) return walesRatesList['corporate_buyer'];
|
8
|
+
return walesRatesList['base'];
|
9
|
+
};
|
10
|
+
|
11
|
+
const ratesList = ratesToCalculateBasedOnTaxType();
|
12
|
+
|
13
|
+
const stampDutyRatesCalculation = ratesList.reduce((accumulator, _, index) => {
|
14
|
+
// Minumun price from the 1st braket should be always 0
|
15
|
+
const minimunFallback = index === 0 ? 0 : Number.POSITIVE_INFINITY;
|
16
|
+
const percentageFromList = +(ratesList[index]['base_ltt_rate']) / 100;
|
17
|
+
const minimumPropertyPrice = ratesList[index]['minimum_property_price'] || minimunFallback;
|
18
|
+
const maximumPropertyPrice = ratesList[index]['maximum_property_price'] || Number.POSITIVE_INFINITY;
|
19
|
+
const rateIndex = `rate${index + 1}`;
|
20
|
+
const rateForTheBracket = calculateRange(price, minimumPropertyPrice, maximumPropertyPrice, percentageFromList);
|
21
|
+
|
22
|
+
accumulator[rateIndex] = rateForTheBracket;
|
23
|
+
accumulator.totalRate += rateForTheBracket;
|
24
|
+
|
25
|
+
accumulator.effectiveRate = (accumulator.totalRate / price) * 100;
|
26
|
+
|
27
|
+
return accumulator;
|
28
|
+
}, {
|
29
|
+
totalRate: 0,
|
30
|
+
effectiveRate: 0,
|
31
|
+
});
|
32
|
+
|
33
|
+
// Roundings
|
34
|
+
stampDutyRatesCalculation.effectiveRate = Math.round(stampDutyRatesCalculation.effectiveRate * 10) / 10;
|
35
|
+
stampDutyRatesCalculation.totalRate = Math.round(stampDutyRatesCalculation.totalRate);
|
36
|
+
|
37
|
+
|
38
|
+
return stampDutyRatesCalculation;
|
39
|
+
};
|
40
|
+
|
41
|
+
export default walesRates;
|
@@ -1,49 +0,0 @@
|
|
1
|
-
import { calculateRange } 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
|
-
|
22
|
-
const stampDutyRatesCalculation = cmsRates.reduce((accumulator, _, index) => {
|
23
|
-
// Minumun price from the 1st braket should be always 0
|
24
|
-
const minimunFallback = index === 0 ? 0 : Number.POSITIVE_INFINITY;
|
25
|
-
const percentageFromList = +(cmsRates[index][buyerStatusAsKeyOfObject()]) / 100;
|
26
|
-
const minimumPropertyPrice = cmsRates[index]['minimum_property_price'] || minimunFallback;
|
27
|
-
const maxisumPropertyPrice = cmsRates[index]['maximum_property_price'] || Number.POSITIVE_INFINITY;
|
28
|
-
const rateIndex = `rate${index + 1}`;
|
29
|
-
const rateForTheBracket = calculateRange(price, minimumPropertyPrice, maxisumPropertyPrice, percentageFromList);
|
30
|
-
|
31
|
-
accumulator[rateIndex] = rateForTheBracket;
|
32
|
-
accumulator.totalRate += rateForTheBracket;
|
33
|
-
|
34
|
-
accumulator.effectiveRate = (accumulator.totalRate / price) * 100;
|
35
|
-
|
36
|
-
return accumulator;
|
37
|
-
}, {
|
38
|
-
totalRate: 0,
|
39
|
-
effectiveRate: 0,
|
40
|
-
});
|
41
|
-
|
42
|
-
// Roundings
|
43
|
-
stampDutyRatesCalculation.effectiveRate = Math.round(stampDutyRatesCalculation.effectiveRate * 10) / 10;
|
44
|
-
stampDutyRatesCalculation.totalRate = Math.round(stampDutyRatesCalculation.totalRate);
|
45
|
-
|
46
|
-
return stampDutyRatesCalculation;
|
47
|
-
};
|
48
|
-
|
49
|
-
export default countryRates;
|