Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions packages/prices/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module"
},
"plugins": ["prettier", "@typescript-eslint"],
"rules": {
"eqeqeq": ["warn", "allow-null"],
"@typescript-eslint/no-unused-vars": [
"error",
{
"ignoreRestSiblings": true,
"varsIgnorePattern": "^_",
"argsIgnorePattern": "^_"
}
],
"no-var": "error",
"no-with": "warn",
"prefer-const": "error"
}
}
3 changes: 3 additions & 0 deletions packages/prices/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.log
dist
node_modules
53 changes: 53 additions & 0 deletions packages/prices/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"name": "@js-ligo/prices",
"version": "1.0.0",
"description": "",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": "./dist/index.js"
},
"files": [
"dist"
],
"scripts": {
"build:clean": "del dist",
"build:js": "swc src -d ./dist --config-file ../../.swcrc",
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
"build": "pnpm build:clean && pnpm build:types && pnpm build:js",
"test": "node --experimental-vm-modules ../../node_modules/jest/bin/jest.js",
"lint": "eslint src/* test/* --fix",
"prepare": "pnpm build"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@js-ligo/vocab": "workspace:^0.3.0"
},
"jest": {
"extensionsToTreatAsEsm": [
".ts"
],
"moduleNameMapper": {
"^(\\.{1,2}/.*)\\.js$": "$1"
},
"transform": {
"^.+\\.(t|j)s$": [
"@swc/jest",
{
"root": "../.."
}
]
}
},
"devDependencies": {
"@typescript-eslint/parser": "^4.9.1",
"eslint": "^6.0.0",
"jest-environment-node": "^29.0.3",
"multiformats": "^9.9.0",
"node-fetch": "*",
"typescript": "^4.7.4"
}
}
1 change: 1 addition & 0 deletions packages/prices/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./prices";
203 changes: 203 additions & 0 deletions packages/prices/src/prices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
/* eslint-disable eqeqeq */
import {
LigoAgreementState,
PriceSpecification,
RentalCarReservation,
} from "@js-ligo/vocab";

export class Prices {
/**
* Find Total Price
// Case 1: Base Price per day
// Case 2: Base price per kilometer
// Case 3: Base price per day + X$ per kilometer over Y range
// Case 4: Base price per hour
// Case 5: Different price per day
// Case 6: Monthly Subscription of X$
// Case 7: Discount for Y+ days
*/
async calculateTotalPrice(
_priceSpecifications: PriceSpecification[],
_rentalCarReservation: RentalCarReservation,
_ligoAgreementState: LigoAgreementState
) {
let sum = 0;
for (let i = 0; i < _priceSpecifications.length; i++) {
if (_priceSpecifications[i].referenceQuantity?.unitCode === "DAY") {
sum =
sum +
(await this._totalPriceDays(
_priceSpecifications[i],
_rentalCarReservation
));
} else if (
_priceSpecifications[i].referenceQuantity?.unitCode === "KMT" ||
_priceSpecifications[i].referenceQuantity?.unitCode === "SMI"
) {
sum =
sum +
(await this._totalPriceKM(
_priceSpecifications[i],
_ligoAgreementState
));
} else if (
_priceSpecifications[i].referenceQuantity?.unitCode === "HUR"
) {
sum =
sum +
(await this._totalPriceHour(
_priceSpecifications[i],
_rentalCarReservation
));
} else if (
_priceSpecifications[i].referenceQuantity?.unitCode === "MON"
) {
sum = sum + (await this._totalMonthlySub(_priceSpecifications[i]));
}
}
return sum;
}

private async _totalPriceDays(
_priceSpecification: PriceSpecification,
_rentalCarReservation: RentalCarReservation
) {
//Filter ValidFrom and ValidThrough
const validF = new Date(
_priceSpecification.validFrom
? _priceSpecification.validFrom
: _rentalCarReservation.pickupTime
);
const validT = new Date(
_priceSpecification.validThrough
? _priceSpecification.validThrough
: _rentalCarReservation.dropoffTime
);
const dropoffT = new Date(_rentalCarReservation.dropoffTime);
const pickupT = new Date(_rentalCarReservation.pickupTime);
const a = validF >= pickupT ? validF : pickupT;
const b = validT <= dropoffT ? validT : dropoffT;

// For discount maxValue
if (_priceSpecification.eligibleQuantity?.maxValue != null) {
return (
_priceSpecification.eligibleQuantity?.maxValue *
_priceSpecification.price
);
}
// For discount minValue
if (_priceSpecification.eligibleQuantity?.minValue != null) {
return (
((await this._dateDiffInDays(a, b)) -
_priceSpecification.eligibleQuantity?.minValue) *
_priceSpecification.price
);
}
// Normal days
return (await this._dateDiffInDays(a, b)) * _priceSpecification.price;
}

private async _totalPriceKM(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function assuming that the unitCode for the startOdometer and endOdometer is the same as the PriceSpecification? This isn't a safe assumption. What should be done if the units are not the same?

To keep it simple, I think a per distance fee should only be charged if there is a PriceSpecification for the correct unit and leave it up to the host to published a per distance fee for each unit separately.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added conversion for SMI to KMT. Let me know your thoughts on it.

_priceSpecification: PriceSpecification,
_ligoAgreementState: LigoAgreementState
) {
if (
_ligoAgreementState.startOdometer?.value != null &&
_ligoAgreementState.endOdometer?.value != null
) {
if (_priceSpecification.eligibleQuantity?.minValue != null) {
if (
Math.abs(
_ligoAgreementState.endOdometer.value -
_ligoAgreementState.startOdometer.value
) >= _priceSpecification.eligibleQuantity?.minValue
) {
if (_priceSpecification.referenceQuantity?.unitCode == "SMI") {
return (
Math.abs(
Math.abs(
_ligoAgreementState.endOdometer.value -
_ligoAgreementState.startOdometer.value
) - _priceSpecification.eligibleQuantity?.minValue
) *
1.609344 *
_priceSpecification.price // 1 SMI = 1.609344 KMT
);
} else {
return (
Math.abs(
Math.abs(
_ligoAgreementState.endOdometer.value -
_ligoAgreementState.startOdometer.value
) - _priceSpecification.eligibleQuantity?.minValue
) * _priceSpecification.price
);
}
}
}
{
if (_priceSpecification.referenceQuantity?.unitCode == "SMI") {
return (
Math.abs(
_ligoAgreementState.endOdometer.value -
_ligoAgreementState.startOdometer.value
) *
1.609344 * // 1 SMI = 1.609344 KMT
_priceSpecification.price
);
} else {
return (
Math.abs(
_ligoAgreementState.endOdometer.value -
_ligoAgreementState.startOdometer.value
) * _priceSpecification.price
);
}
}
} else return 0;
}

private async _totalPriceHour(
_priceSpecification: PriceSpecification,
_rentalCarReservation: RentalCarReservation
) {
const a = new Date(_rentalCarReservation.dropoffTime);
const b = new Date(_rentalCarReservation.pickupTime);
return (
(await Math.abs(await this._hourDiffInDays(a, b))) *
_priceSpecification.price
);
}

private async _totalMonthlySub(_priceSpecification: PriceSpecification) {
if (_priceSpecification.billingIncrement != null) {
return _priceSpecification.price * _priceSpecification.billingIncrement;
}
return 0;
}

private async _dateDiffInDays(a: Date, b: Date) {
const _MS_PER_DAY = 1000 * 60 * 60 * 24;
// Discard the time and time-zone information.
const utc1 = Date.UTC(a.getFullYear(), a.getMonth(), a.getDate());
const utc2 = Date.UTC(b.getFullYear(), b.getMonth(), b.getDate());
return Math.floor((utc2 - utc1) / _MS_PER_DAY);
}

private async _hourDiffInDays(a: Date, b: Date) {
const _MS_PER_HOUR = 1000 * 60 * 60;
const utc1 = Date.UTC(
a.getFullYear(),
a.getMonth(),
a.getDate(),
a.getHours()
);
const utc2 = Date.UTC(
b.getFullYear(),
b.getMonth(),
b.getDate(),
b.getHours()
);
return Math.floor((utc2 - utc1) / _MS_PER_HOUR);
}
}
Loading