@stll/money 0.2.3 → 0.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.
- package/dist/index.d.ts +6 -0
- package/dist/index.js +32 -12
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -110,6 +110,12 @@ export type ProrateHourlyCentsInput = {
|
|
|
110
110
|
hourlyRateCents: CentsAmount;
|
|
111
111
|
};
|
|
112
112
|
export declare const prorateHourlyCents: ({ billedMinutes, hourlyRateCents }: ProrateHourlyCentsInput) => CentsAmount;
|
|
113
|
+
type TimeEntryAmountInput = {
|
|
114
|
+
billedMinutes: number;
|
|
115
|
+
rateAtEntry: CentsAmount;
|
|
116
|
+
noCharge: boolean;
|
|
117
|
+
};
|
|
118
|
+
export declare const timeEntryAmount: (entry: TimeEntryAmountInput) => CentsAmount;
|
|
113
119
|
export type ApplyMarkupCentsInput = {
|
|
114
120
|
amountCents: CentsAmount;
|
|
115
121
|
markupPercent: number;
|
package/dist/index.js
CHANGED
|
@@ -171,18 +171,34 @@ const toMajorUnits = ({ amountCents, currency }) => amountCents / 10 ** currency
|
|
|
171
171
|
* RangeError would take the whole board down with it.
|
|
172
172
|
*/
|
|
173
173
|
const formatMoneyCents = ({ amountCents, currency, locale, fractionDigits }) => {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
const minorDigits = currencyMinorUnitDigits(currency);
|
|
175
|
+
const digits = fractionDigits ?? minorDigits;
|
|
176
|
+
if (!Number.isInteger(digits) || digits < 0 || digits > 100) return panic("Money fraction digits must be an integer from 0 to 100");
|
|
177
|
+
const magnitude = BigInt(Math.abs(cents(amountCents)));
|
|
178
|
+
const negative = amountCents < 0 || Object.is(amountCents, -0);
|
|
179
|
+
const displayUnits = digits >= minorDigits ? magnitude * 10n ** BigInt(digits - minorDigits) : (magnitude + 10n ** BigInt(minorDigits - digits) / 2n) / 10n ** BigInt(minorDigits - digits);
|
|
180
|
+
const scale = 10n ** BigInt(digits);
|
|
181
|
+
const whole = displayUnits / scale;
|
|
182
|
+
const fraction = (displayUnits % scale).toString().padStart(digits, "0");
|
|
183
|
+
const formatted = Result.try(() => {
|
|
184
|
+
const formatter = new Intl.NumberFormat(locale, {
|
|
185
|
+
style: "currency",
|
|
186
|
+
currency,
|
|
187
|
+
minimumFractionDigits: digits,
|
|
188
|
+
maximumFractionDigits: digits
|
|
189
|
+
});
|
|
190
|
+
const digitFormatter = new Intl.NumberFormat(locale, { useGrouping: false });
|
|
191
|
+
const localizedFraction = fraction.split("").map((digit) => digitFormatter.format(Number(digit))).join("");
|
|
192
|
+
const negativeSubunit = negative && whole === 0n;
|
|
193
|
+
let template = whole;
|
|
194
|
+
if (negative) template = negativeSubunit ? -1n : -whole;
|
|
195
|
+
return formatter.formatToParts(template).map((part) => {
|
|
196
|
+
if (part.type === "fraction") return localizedFraction;
|
|
197
|
+
if (negativeSubunit && part.type === "integer") return digitFormatter.format(0);
|
|
198
|
+
return part.value;
|
|
199
|
+
}).join("");
|
|
177
200
|
});
|
|
178
|
-
|
|
179
|
-
const formatted = Result.try(() => new Intl.NumberFormat(locale, {
|
|
180
|
-
style: "currency",
|
|
181
|
-
currency,
|
|
182
|
-
minimumFractionDigits: digits,
|
|
183
|
-
maximumFractionDigits: digits
|
|
184
|
-
}).format(major));
|
|
185
|
-
return formatted.isErr() ? `${major.toFixed(digits)} ${currency}` : formatted.value;
|
|
201
|
+
return formatted.isErr() ? `${negative ? "-" : ""}${whole}${digits === 0 ? "" : `.${fraction}`} ${currency}` : formatted.value;
|
|
186
202
|
};
|
|
187
203
|
//#endregion
|
|
188
204
|
//#region src/index.ts
|
|
@@ -212,6 +228,10 @@ const prorateHourlyCents = ({ billedMinutes, hourlyRateCents }) => {
|
|
|
212
228
|
const product = BigInt(billedMinutes) * BigInt(hourlyRateCents);
|
|
213
229
|
return cents(Number((product + 30n) / 60n));
|
|
214
230
|
};
|
|
231
|
+
const timeEntryAmount = (entry) => entry.noCharge ? cents(0) : prorateHourlyCents({
|
|
232
|
+
billedMinutes: entry.billedMinutes,
|
|
233
|
+
hourlyRateCents: entry.rateAtEntry
|
|
234
|
+
});
|
|
215
235
|
const applyMarkupCents = ({ amountCents, markupPercent }) => {
|
|
216
236
|
assertNonNegativeInteger("amountCents", amountCents);
|
|
217
237
|
assertNonNegativeInteger("markupPercent", markupPercent);
|
|
@@ -277,4 +297,4 @@ var MoneyTotals = class {
|
|
|
277
297
|
}
|
|
278
298
|
};
|
|
279
299
|
//#endregion
|
|
280
|
-
export { MoneyTotals, addCents, applyMarkupCents, cents, currencyCents, currencyMinorUnitDigits, formatMoneyCents, prorateHourlyCents, toMajorUnits, toMinorUnits, tryToMinorUnits, unsafeCents };
|
|
300
|
+
export { MoneyTotals, addCents, applyMarkupCents, cents, currencyCents, currencyMinorUnitDigits, formatMoneyCents, prorateHourlyCents, timeEntryAmount, toMajorUnits, toMinorUnits, tryToMinorUnits, unsafeCents };
|