Pricing needs to remain consistent across the site, from barrier, to marketing popup, to signup confirmation page.
This small library allows the validation and manipulation of currencies and pricing, and performs pricing transformations.
Price
Monthly
Quarterly
Yearly
npm install --save @financial-times/n-pricing
const Price = require('@financial-times/n-pricing').Price;
new Price().get()
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: 'GBP0.00', _rawValue: {} }
new Price({ value: 1 }).get()
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: 'GBP1.00', _rawValue: 1 }
new Price({ value: 1, symbol: '£' }).get() // £1
new Price({ value: 1, currency: 'JPY' }).getAmount() // JPY1
new Price({ value: 1, currency: 'JPY', symbol: '¥' }).getAmount() // ¥1
new Price({ value: 1, currency: 'HKD', nativeSymbol: '$' }).price
// { amount: { symbol: 'HKD', nativeSymbol: '$', currency: 'HKD', value: 'HKD1.00', _rawValue: 1 }
new Price({ value: 1, currency: 'HKD', nativeSymbol: '$', trimDecimalsWhenWhole: true }).price
// { amount: { symbol: 'HKD', nativeSymbol: '$', currency: 'HKD', value: 'HKD1.00', _rawValue: 1 }
new Price({ value: 1 }).discount( -0.5 ).get()
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: 'GBP0.50', _rawValue: 1 }
new Price({ value: 1, symbol: '£' }).discount( -0.5 ).getAmount() // £0.50
The .compare()
method returns savings in value difference and as a percentage.
Negative values indicate a markup, i.e. the stored value of the object is higher than the value we are comparing against.
new Price({ value: 10 }).compare( 8 ) // { value: '-GBP2.00', percentage: '-20%' }
new Price({ value: 8, symbol: '£'}).compare( 10 ) // { value: '£2.00', percentage: '25%'}
The .getAmountFormatted()
method returns values formatted based on the options.
The options are:
-
trimDecimalsWhenWhole
- Boolean that determines whether to remove the decimal part of the amount if it is a whole number. Default value isfalse
.
new Price({ value: 10 }).getAmountFormatted({ trimDecimalsWhenWhole: true }); // Returns 'GBP10'
new Price({ value: 10.25, symbol: '£' }).getAmountFormatted({ trimDecimalsWhenWhole: true }); // Returns '£10.25'
You're able to return pricing and percentage information without symbols interpolated by passing in an uninterpolated
flag as follows:
NB: Only use this if you have some specific reason that falls outside the remit of this module.
new Price({ value: 1 }, { uninterpolated: true }).get()
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: '1.00', _rawValue: 1 }
new Price({ value: 1, currency: 'JPY' }, { uninterpolated: true }).getAmount() // 1.00
new Price({ value: 1 }, { uninterpolated: true }).discount( -0.5 ).get()
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: '0.50', _rawValue: 1 }
new Price({ value: 10 }, { uninterpolated: true }).compare( 8 ) // { value: '-2.00', percentage: '-20'}
Offer pricing is either annual, monthly or quarterly. We often display pricing translated into its weekly cost.
Monthly
, Yearly
and Quarterly
extend the Price
class to offer some useful pricing transformations that allow for all alternative breakdowns of cost.
const Monthly = require('@financial-times/n-pricing').Monthly;
const Yearly = require('@financial-times/n-pricing').Yearly;
const Quarterly = require('@financial-times/n-pricing').Quarterly;
new Monthly({ value: 1 }).get('yearly')
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: 'GBP12.00' _rawValue: '12' }
new Yearly({ value: 96.45 }).get('monthly')
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: 'GBP8.04', _rawValue: '8.0375' }
new Quarterly({ value: 30 }).get('yearly')
// { symbol: 'GBP', nativeSymbol: 'GBP', currency: 'GBP', value: 'GBP120.00', _rawValue: '120' }
new Monthly({ value: 1, currency: 'OMR', nativeSymbol: '﷼' }).getAmount('weekly') // OMR0.24
new Monthly({ value: 1, symbol: '£' }).price
/*
{
yearly: {
amount: { symbol: '£', nativeSymbol: '£', currency: 'GBP', value: '£12.00', _rawValue: '12' }
},
quarterly: {
amount: { symbol: '£', nativeSymbol: '£', currency: 'GBP', value: '£3.00', _rawValue: '3' }
},
monthly: {
amount: { symbol: '£', nativeSymbol: '£', currency: 'GBP', value: '£1.00', _rawValue: 1 }
},
weekly: {
amount: { symbol: '£', nativeSymbol: '£', currency: 'GBP', value: '£0.24', _rawValue: '0.230769230...' }
},
daily: {
amount: { symbol: '£', nativeSymbol: '£', currency: 'GBP', value: '£0.04', _rawValue: '0.032876712...' }
}
}
*/
let yearlyPrice = new Yearly({ value: 10 });
let monthlyPrice = new Monthly({ value: 1 });
yearlyPrice.compare( monthlyPrice.get('yearly') )
// { value: 'GBP2.00', percentage: '20%'}
// annual pricing at £10 offers a 20% saving over paying £1 a month
We use big.js
to handle decimal arithmetic.
We use the ROUND_UP
rounding method in our calculations: http://mikemcl.github.io/big.js/#rm
Rounds away from zero.
Offers originally have their priced expressed as either x per Year
, x per Month
or x per Quarter
. From this we may want to display an expression of the price weekly
or daily
.
Using the table below. input 12 per Year
would be displayed as output 1 per Month
.
Input Original Price Expression (val) | Output Expression | Calculation |
---|---|---|
Yearly | Monthly | val/12 |
Quarterly | val/4 |
|
Weekly | val/52 |
|
Daily | val/365 |
|
Monthly | Yearly | val*12 |
Quarterly | val*3 |
|
Weekly | (val*12)/52 |
|
Daily | (val*12)/365 |
|
Quarterly | Yearly | val*4 |
Monthly | val/3 |
|
Weekly | val/13 |
|
Daily | (val*4)/365 |