pricing4ts
Version:
 Pricing4TS is a TypeScript-based toolkit designed to enhance the server-side functionality of a pricing-driven SaaS by enabling the seamless integration of pricing plans into the application logic. T
271 lines (270 loc) • 20.3 kB
JavaScript
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var minizinc_1 = __importDefault(require("../models/minizinc/minizinc"));
var pricing_dzn_exporter_1 = require("../utils/dzn-exporter/pricing-dzn-exporter");
var minizinc_2 = require("../models/minizinc/minizinc");
var minizinc_explanator_1 = require("../utils/minizinc-explanator");
var plan_1 = require("../../main/models/pricing2yaml/plan");
var addon_1 = require("../../main/models/pricing2yaml/addon");
var defaultAnalyticsOptions = {
printDzn: false
};
var PricingService = /** @class */ (function () {
function PricingService(pricing) {
this.pricing = pricing;
}
PricingService.prototype.runPricingOperation = function (pricingOperation) {
return __awaiter(this, void 0, void 0, function () {
var dznPricing, model;
return __generator(this, function (_a) {
dznPricing = (0, pricing_dzn_exporter_1.pricing2DZN)(this.pricing);
model = new minizinc_1.default();
return [2 /*return*/, model.runPricingOperation(pricingOperation, dznPricing)];
});
});
};
PricingService.prototype.getConfigurationSpace = function () {
return __awaiter(this, void 0, void 0, function () {
var dznPricing, configurationSpace, result, allSolutions, _i, allSolutions_1, solution, selectedPlan, selectedAddons, subscriptionFeatures, subscriptionUsageLimits, e_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dznPricing = (0, pricing_dzn_exporter_1.pricing2DZN)(this.pricing);
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
configurationSpace = [];
return [4 /*yield*/, this._getConfigurationSpace(dznPricing)];
case 2:
result = _a.sent();
allSolutions = result.allSolutions;
for (_i = 0, allSolutions_1 = allSolutions; _i < allSolutions_1.length; _i++) {
solution = allSolutions_1[_i];
selectedPlan = Object.keys(this.pricing.plans)[solution.selected_plan - 1];
selectedAddons = solution.selected_addons.map(function (addonIndex, index) { return addonIndex === 1 ? Object.keys(_this.pricing.addOns)[index] : null; }).filter(function (addon) { return addon !== null; });
subscriptionFeatures = solution.subscription_features.map(function (featureIndex, index) { return featureIndex === 1 ? Object.keys(_this.pricing.features)[index] : null; }).filter(function (feature) { return feature !== null; });
subscriptionUsageLimits = solution.subscription_usage_limits.map(function (usageLimitIndex, index) { return usageLimitIndex === 1 ? Object.keys(_this.pricing.usageLimits)[index] : null; }).filter(function (usageLimit) { return usageLimit !== null; });
configurationSpace.push({
selectedPlan: selectedPlan,
selectedAddons: selectedAddons,
subscriptionFeatures: subscriptionFeatures,
subscriptionUsageLimits: subscriptionUsageLimits,
subscriptionCost: solution.subscription_cost
});
}
return [2 /*return*/, configurationSpace];
case 3:
e_1 = _a.sent();
throw new Error(e_1.message);
case 4: return [2 /*return*/];
}
});
});
};
PricingService.prototype.getAnalytics = function (analyticsOptions) {
return __awaiter(this, void 0, void 0, function () {
var dznPricing, _a, configurationSpaceResult, minSubscriptionPriceResult, maxSubscriptionPriceResult, informationFeatures, integrationFeatures, domainFeatures, automationFeatures, managementFeatures, guaranteeFeatures, supportFeatures, paymentFeatures, numberOfFeatures, numberOfInformationFeatures, numberOfIntegrationFeatures, numberOfIntegrationApiFeatures, numberOfIntegrationExtensionFeatures, numberOfIntegrationIdentityProviderFeatures, numberOfIntegrationWebSaaSFeatures, numberOfIntegrationMarketplaceFeatures, numberOfIntegrationExternalDeviceFeatures, numberOfDomainFeatures, numberOfAutomationFeatures, numberOfBotAutomationFeatures, numberOfFilteringAutomationFeatures, numberOfTrackingAutomationFeatures, numberOfTaskAutomationFeatures, numberOfManagementFeatures, numberOfGuaranteeFeatures, numberOfSupportFeatures, numberOfPaymentFeatures, numberOfUsageLimits, numberOfRenewableUsageLimits, numberOfNonRenewableUsageLimits, numberOfPlans, numberOfFreePlans, numberOfPaidPlans, numberOfAddOns, numberOfReplacementAddons, numberOfExtensionAddons, configurationSpaceSize, minSubscriptionPrice, maxSubscriptionPrice, e_2;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!analyticsOptions) {
analyticsOptions = defaultAnalyticsOptions;
}
else {
analyticsOptions = __assign(__assign({}, defaultAnalyticsOptions), analyticsOptions);
}
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
dznPricing = (0, pricing_dzn_exporter_1.pricing2DZN)(this.pricing);
if (analyticsOptions.printDzn) {
console.log(dznPricing);
}
return [4 /*yield*/, Promise.all([
this._getConfigurationSpace(dznPricing),
this._getMinSubscriptionPrice(dznPricing),
this._getMaxSubscriptionPrice(dznPricing)
]).catch(function (e) {
throw new Error((0, minizinc_explanator_1.explain)(e, _this.pricing));
})];
case 2:
_a = _b.sent(), configurationSpaceResult = _a[0], minSubscriptionPriceResult = _a[1], maxSubscriptionPriceResult = _a[2];
informationFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "INFORMATION"; });
integrationFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "INTEGRATION"; });
domainFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "DOMAIN"; });
automationFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "AUTOMATION"; });
managementFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "MANAGEMENT"; });
guaranteeFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "GUARANTEE"; });
supportFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "SUPPORT"; });
paymentFeatures = Object.values(this.pricing.features).filter(function (f) { return f.type === "PAYMENT"; });
numberOfFeatures = Object.values(this.pricing.features).length;
numberOfInformationFeatures = informationFeatures.length;
numberOfIntegrationFeatures = integrationFeatures.length;
numberOfIntegrationApiFeatures = integrationFeatures.filter(function (f) { return f.integrationType === "API"; }).length;
numberOfIntegrationExtensionFeatures = integrationFeatures.filter(function (f) { return f.integrationType === "EXTENSION"; }).length;
numberOfIntegrationIdentityProviderFeatures = integrationFeatures.filter(function (f) { return f.integrationType === "IDENTITY_PROVIDER"; }).length;
numberOfIntegrationWebSaaSFeatures = integrationFeatures.filter(function (f) { return f.integrationType === "WEB_SAAS"; }).length;
numberOfIntegrationMarketplaceFeatures = integrationFeatures.filter(function (f) { return f.integrationType === "MARKETPLACE"; }).length;
numberOfIntegrationExternalDeviceFeatures = integrationFeatures.filter(function (f) { return f.integrationType === "EXTERNAL_DEVICE"; }).length;
numberOfDomainFeatures = domainFeatures.length;
numberOfAutomationFeatures = automationFeatures.length;
numberOfBotAutomationFeatures = automationFeatures.filter(function (f) { return f.automationType === "BOT"; }).length;
numberOfFilteringAutomationFeatures = automationFeatures.filter(function (f) { return f.automationType === "FILTERING"; }).length;
numberOfTrackingAutomationFeatures = automationFeatures.filter(function (f) { return f.automationType === "TRACKING"; }).length;
numberOfTaskAutomationFeatures = automationFeatures.filter(function (f) { return f.automationType === "TASK_AUTOMATION"; }).length;
numberOfManagementFeatures = managementFeatures.length;
numberOfGuaranteeFeatures = guaranteeFeatures.length;
numberOfSupportFeatures = supportFeatures.length;
numberOfPaymentFeatures = paymentFeatures.length;
numberOfUsageLimits = this.pricing.usageLimits ? Object.values(this.pricing.usageLimits).length : 0;
numberOfRenewableUsageLimits = this.pricing.usageLimits ? Object.values(this.pricing.usageLimits).filter(function (ul) { return ul.type === "RENEWABLE"; }).length : 0;
numberOfNonRenewableUsageLimits = this.pricing.usageLimits ? Object.values(this.pricing.usageLimits).filter(function (ul) { return ul.type === "NON_RENEWABLE"; }).length : 0;
numberOfPlans = this.pricing.plans ? Object.values(this.pricing.plans).length : 0;
numberOfFreePlans = this.pricing.plans ? Object.values(this.pricing.plans).filter(function (p) { return p.price === 0; }).length : 0;
numberOfPaidPlans = this.pricing.plans ? Object.values(this.pricing.plans).filter(function (p) { return typeof (p.price) === "number" ? p.price > 0 : true; }).length : 0;
numberOfAddOns = this.pricing.addOns ? Object.values(this.pricing.addOns).length : 0;
numberOfReplacementAddons = this.pricing.addOns ? Object.values(this.pricing.addOns).filter(function (a) { return a.features || a.usageLimits; }).length : 0;
numberOfExtensionAddons = this.pricing.addOns ? Object.values(this.pricing.addOns).filter(function (a) { return a.features || a.usageLimits ? false : a.usageLimitsExtensions; }).length : 0;
configurationSpaceSize = configurationSpaceResult.statistics.nSolutions;
minSubscriptionPrice = configurationSpaceSize !== 0 ? this._computeConfigurationPrice(minSubscriptionPriceResult.solution.output.json) : NaN;
maxSubscriptionPrice = configurationSpaceSize !== 0 ? this._computeConfigurationPrice(maxSubscriptionPriceResult.solution.output.json) : NaN;
return [2 /*return*/, {
numberOfFeatures: numberOfFeatures,
numberOfInformationFeatures: numberOfInformationFeatures,
numberOfIntegrationFeatures: numberOfIntegrationFeatures,
numberOfIntegrationApiFeatures: numberOfIntegrationApiFeatures,
numberOfIntegrationExtensionFeatures: numberOfIntegrationExtensionFeatures,
numberOfIntegrationIdentityProviderFeatures: numberOfIntegrationIdentityProviderFeatures,
numberOfIntegrationWebSaaSFeatures: numberOfIntegrationWebSaaSFeatures,
numberOfIntegrationMarketplaceFeatures: numberOfIntegrationMarketplaceFeatures,
numberOfIntegrationExternalDeviceFeatures: numberOfIntegrationExternalDeviceFeatures,
numberOfDomainFeatures: numberOfDomainFeatures,
numberOfAutomationFeatures: numberOfAutomationFeatures,
numberOfBotAutomationFeatures: numberOfBotAutomationFeatures,
numberOfFilteringAutomationFeatures: numberOfFilteringAutomationFeatures,
numberOfTrackingAutomationFeatures: numberOfTrackingAutomationFeatures,
numberOfTaskAutomationFeatures: numberOfTaskAutomationFeatures,
numberOfManagementFeatures: numberOfManagementFeatures,
numberOfGuaranteeFeatures: numberOfGuaranteeFeatures,
numberOfSupportFeatures: numberOfSupportFeatures,
numberOfPaymentFeatures: numberOfPaymentFeatures,
numberOfUsageLimits: numberOfUsageLimits,
numberOfRenewableUsageLimits: numberOfRenewableUsageLimits,
numberOfNonRenewableUsageLimits: numberOfNonRenewableUsageLimits,
numberOfPlans: numberOfPlans,
numberOfFreePlans: numberOfFreePlans,
numberOfPaidPlans: numberOfPaidPlans,
numberOfAddOns: numberOfAddOns,
numberOfReplacementAddons: numberOfReplacementAddons,
numberOfExtensionAddons: numberOfExtensionAddons,
configurationSpaceSize: configurationSpaceSize,
minSubscriptionPrice: parseFloat(minSubscriptionPrice.toFixed(2)),
maxSubscriptionPrice: parseFloat(maxSubscriptionPrice.toFixed(2)),
}];
case 3:
e_2 = _b.sent();
throw new Error(e_2.message);
case 4: return [2 /*return*/];
}
});
});
};
PricingService.prototype._getConfigurationSpace = function (dznPricing) {
return __awaiter(this, void 0, void 0, function () {
var model;
return __generator(this, function (_a) {
model = new minizinc_1.default();
return [2 /*return*/, model.runPricingOperation(minizinc_2.PricingOperation.CONFIGURATION_SPACE, dznPricing)];
});
});
};
PricingService.prototype._getMinSubscriptionPrice = function (dznPricing) {
return __awaiter(this, void 0, void 0, function () {
var model;
return __generator(this, function (_a) {
model = new minizinc_1.default();
return [2 /*return*/, model.runPricingOperation(minizinc_2.PricingOperation.CHEAPEST_SUBSCRIPTION, dznPricing)];
});
});
};
PricingService.prototype._getMaxSubscriptionPrice = function (dznPricing) {
return __awaiter(this, void 0, void 0, function () {
var model;
return __generator(this, function (_a) {
model = new minizinc_1.default();
return [2 /*return*/, model.runPricingOperation(minizinc_2.PricingOperation.MOST_EXPENSIVE_SUBSCRIPTION, dznPricing)];
});
});
};
PricingService.prototype._computeConfigurationPrice = function (minizincSolution) {
var plansPrices = (0, plan_1.getPlanPrices)(this.pricing.plans);
var addOnPrices = (0, addon_1.getAddOnPrices)(this.pricing.addOns);
var configurationPrice = 0;
if (plansPrices.length > 0) {
configurationPrice += plansPrices[minizincSolution.selected_plan - 1];
}
if (addOnPrices.length > 0) {
for (var i = 0; i < minizincSolution.selected_addons.length; i++) {
var item = minizincSolution.selected_addons[i];
if (item === 1) {
configurationPrice += addOnPrices[i];
}
}
}
return configurationPrice;
};
return PricingService;
}());
exports.default = PricingService;