aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Cheng <[email protected]>2024-03-01 17:23:52 -0500
committerGitHub <[email protected]>2024-03-01 23:23:52 +0100
commit9348138893bb95faa5037c653443fbd525ce2939 (patch)
tree8823ebdf2f7ea6e934c7e407f0f6b497dffeddba /src
parent8e880c15da8901eb4694273a79ea4fcd908d1c3f (diff)
downloadfaker-9348138893bb95faa5037c653443fbd525ce2939.tar.xz
faker-9348138893bb95faa5037c653443fbd525ce2939.zip
fix(commerce): return fractional prices (#2458)
Co-authored-by: ST-DDT <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/modules/commerce/index.ts93
1 files changed, 76 insertions, 17 deletions
diff --git a/src/modules/commerce/index.ts b/src/modules/commerce/index.ts
index 6750299b..fa3efb26 100644
--- a/src/modules/commerce/index.ts
+++ b/src/modules/commerce/index.ts
@@ -116,6 +116,13 @@ export class CommerceModule extends ModuleBase {
/**
* Generates a price between min and max (inclusive).
*
+ * To better represent real-world prices, when `options.dec` is greater than `0`, the final decimal digit in the returned string will be generated as follows:
+ *
+ * - 50% of the time: `9`
+ * - 30% of the time: `5`
+ * - 10% of the time: `0`
+ * - 10% of the time: a random digit from `0` to `9`
+ *
* @param options An options object.
* @param options.min The minimum price. Defaults to `1`.
* @param options.max The maximum price. Defaults to `1000`.
@@ -123,9 +130,9 @@ export class CommerceModule extends ModuleBase {
* @param options.symbol The currency value to use. Defaults to `''`.
*
* @example
- * faker.commerce.price() // 828.00
- * faker.commerce.price({ min: 100 }) // 904.00
- * faker.commerce.price({ min: 100, max: 200 }) // 154.00
+ * faker.commerce.price() // 828.07
+ * faker.commerce.price({ min: 100 }) // 904.19
+ * faker.commerce.price({ min: 100, max: 200 }) // 154.55
* faker.commerce.price({ min: 100, max: 200, dec: 0 }) // 133
* faker.commerce.price({ min: 100, max: 200, dec: 0, symbol: '$' }) // $114
*
@@ -160,15 +167,22 @@ export class CommerceModule extends ModuleBase {
/**
* Generates a price between min and max (inclusive).
*
+ * To better represent real-world prices, when `options.dec` is greater than `0`, the final decimal digit in the returned string will be generated as follows:
+ *
+ * - 50% of the time: `9`
+ * - 30% of the time: `5`
+ * - 10% of the time: `0`
+ * - 10% of the time: a random digit from `0` to `9`
+ *
* @param min The minimum price. Defaults to `1`.
* @param max The maximum price. Defaults to `1000`.
* @param dec The number of decimal places. Defaults to `2`.
* @param symbol The currency value to use. Defaults to `''`.
*
* @example
- * faker.commerce.price() // 828.00
- * faker.commerce.price(100) // 904.00
- * faker.commerce.price(100, 200) // 154.00
+ * faker.commerce.price() // 828.07
+ * faker.commerce.price(100) // 904.19
+ * faker.commerce.price(100, 200) // 154.55
* faker.commerce.price(100, 200, 0) // 133
* faker.commerce.price(100, 200, 0, '$') // $114
*
@@ -180,7 +194,14 @@ export class CommerceModule extends ModuleBase {
/**
* Generates a price between min and max (inclusive).
*
- * @param options The minimum price or on options object.
+ * To better represent real-world prices, when `options.dec` is greater than `0`, the final decimal digit in the returned string will be generated as follows:
+ *
+ * - 50% of the time: `9`
+ * - 30% of the time: `5`
+ * - 10% of the time: `0`
+ * - 10% of the time: a random digit from `0` to `9`
+ *
+ * @param options The minimum price or an options object.
* @param options.min The minimum price. Defaults to `1`.
* @param options.max The maximum price. Defaults to `1000`.
* @param options.dec The number of decimal places. Defaults to `2`.
@@ -190,9 +211,9 @@ export class CommerceModule extends ModuleBase {
* @param legacySymbol The currency value to use. This argument is deprecated. Defaults to `''`.
*
* @example
- * faker.commerce.price() // 828.00
- * faker.commerce.price({ min: 100 }) // 904.00
- * faker.commerce.price({ min: 100, max: 200 }) // 154.00
+ * faker.commerce.price() // 828.07
+ * faker.commerce.price({ min: 100 }) // 904.19
+ * faker.commerce.price({ min: 100, max: 200 }) // 154.55
* faker.commerce.price({ min: 100, max: 200, dec: 0 }) // 133
* faker.commerce.price({ min: 100, max: 200, dec: 0, symbol: '$' }) // $114
*
@@ -234,7 +255,14 @@ export class CommerceModule extends ModuleBase {
/**
* Generates a price between min and max (inclusive).
*
- * @param options The minimum price or on options object.
+ * To better represent real-world prices, when `options.dec` is greater than `0`, the final decimal digit in the returned string will be generated as follows:
+ *
+ * - 50% of the time: `9`
+ * - 30% of the time: `5`
+ * - 10% of the time: `0`
+ * - 10% of the time: a random digit from `0` to `9`
+ *
+ * @param options The minimum price or an options object.
* @param options.min The minimum price. Defaults to `1`.
* @param options.max The maximum price. Defaults to `1000`.
* @param options.dec The number of decimal places. Defaults to `2`.
@@ -244,9 +272,9 @@ export class CommerceModule extends ModuleBase {
* @param legacySymbol The currency value to use. This argument is deprecated. Defaults to `''`.
*
* @example
- * faker.commerce.price() // 828.00
- * faker.commerce.price({ min: 100 }) // 904.00
- * faker.commerce.price({ min: 100, max: 200 }) // 154.00
+ * faker.commerce.price() // 828.07
+ * faker.commerce.price({ min: 100 }) // 904.19
+ * faker.commerce.price({ min: 100, max: 200 }) // 154.55
* faker.commerce.price({ min: 100, max: 200, dec: 0 }) // 133
* faker.commerce.price({ min: 100, max: 200, dec: 0, symbol: '$' }) // $114
*
@@ -286,10 +314,41 @@ export class CommerceModule extends ModuleBase {
return `${symbol}0`;
}
- // TODO @Shinigami92 2022-11-24: https://github.com/faker-js/faker/issues/350
- const randValue = this.faker.number.int({ min, max });
+ if (min === max) {
+ return `${symbol}${min.toFixed(dec)}`;
+ }
+
+ const generated = this.faker.number.float({
+ min,
+ max,
+ fractionDigits: dec,
+ });
+
+ if (dec === 0) {
+ return `${symbol}${generated.toFixed(dec)}`;
+ }
+
+ const oldLastDigit = (generated * 10 ** dec) % 10;
+ const newLastDigit = this.faker.helpers.weightedArrayElement([
+ { weight: 5, value: 9 },
+ { weight: 3, value: 5 },
+ { weight: 1, value: 0 },
+ {
+ weight: 1,
+ value: this.faker.number.int({ min: 0, max: 9 }),
+ },
+ ]);
+
+ const fraction = (1 / 10) ** dec;
+ const oldLastDigitValue = oldLastDigit * fraction;
+ const newLastDigitValue = newLastDigit * fraction;
+ const combined = generated - oldLastDigitValue + newLastDigitValue;
+
+ if (min <= combined && combined <= max) {
+ return `${symbol}${combined.toFixed(dec)}`;
+ }
- return symbol + randValue.toFixed(dec);
+ return `${symbol}${generated.toFixed(dec)}`;
}
/**