diff --git a/package.json b/package.json index 16fdefc..388b2c0 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@sinclair/typebox": "^0.32.15", "@supabase/supabase-js": "2.43.1", "commander": "12.0.0", + "decimal.js": "^10.4.3", "dotenv": "^16.4.5", "typebox-validators": "0.3.5" }, diff --git a/src/shared/pricing.ts b/src/shared/pricing.ts index bcb60e4..3b0980d 100644 --- a/src/shared/pricing.ts +++ b/src/shared/pricing.ts @@ -1,10 +1,11 @@ import { Context } from "../types/context"; import { Label } from "../types/github"; +import { Decimal } from "decimal.js"; -export function calculateTaskPrice(context: Context, timeValue: number, priorityValue: number, baseValue?: number): number { +export function calculateTaskPrice(context: Context, timeValue: number, priorityValue: number, baseValue?: number): string { const base = baseValue ?? context.config.basePriceMultiplier; - const priority = priorityValue / 10; // floats cause bad math - return 1000 * base * timeValue * priority; + const priority = new Decimal(priorityValue).div(10); // floats cause bad math + return new Decimal(base).mul(1000).mul(timeValue).mul(priority).toDecimalPlaces(2).toString(); } export function setPrice(context: Context, timeLabel: Label, priorityLabel: Label) { diff --git a/tests/main.test.ts b/tests/main.test.ts index 8237e28..569c52a 100644 --- a/tests/main.test.ts +++ b/tests/main.test.ts @@ -8,6 +8,8 @@ import { server } from "./__mocks__/node"; import issueCommented from "./__mocks__/requests/issue-comment-post.json"; import usersGet from "./__mocks__/users-get.json"; import * as crypto from "crypto"; +import { calculateLabelValue, calculateTaskPrice } from "../src/shared/pricing"; +import { Context } from "../src/types/context"; const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", { modulusLength: 2048, @@ -77,6 +79,53 @@ describe("User tests", () => { }); }); + it("Should accurately calculates prices", () => { + const context = { + config: { + basePriceMultiplier: 3.0, + }, + }; + const priority1 = "1 priority"; + const priority2 = "2 priority"; + const priority3 = "3 priority"; + const testCases = [ + { + timeValue: calculateLabelValue("<1 minutes"), + priorityValue: calculateLabelValue(priority3), + expectedPrice: "1.8", + }, + { + timeValue: calculateLabelValue("<4 hours"), + priorityValue: calculateLabelValue(priority2), + expectedPrice: "300", + }, + { + timeValue: calculateLabelValue("<1 hours"), + priorityValue: calculateLabelValue(priority2), + expectedPrice: "75", + }, + { + timeValue: calculateLabelValue("<1.52 hours"), + priorityValue: calculateLabelValue(priority3), + expectedPrice: "112.5", + }, + { + timeValue: calculateLabelValue("<139.876 minutes"), + priorityValue: calculateLabelValue(priority1), + expectedPrice: "83.4", + }, + { + timeValue: calculateLabelValue("<12.333333 weeks"), + priorityValue: calculateLabelValue(priority2), + expectedPrice: "7800", + }, + ]; + for (const testCase of testCases) { + const price = calculateTaskPrice(context as unknown as Context, testCase.timeValue, testCase.priorityValue); + expect(price).toEqual(testCase.expectedPrice); + } + }); + it("Should handle the comment", async () => { const data = { ...issueCommented,