From eb7b2c5fcfaced60a1700efdd3f7bbc09fd6ec94 Mon Sep 17 00:00:00 2001 From: rechen Date: Thu, 7 May 2020 16:06:54 -0700 Subject: [PATCH 1/8] Added new resourceGuids for Arnold and V-ray RT with correct prices * WIP: adding gpu to possible list of units and replacing perCore --- .../app-license-picker.component.ts | 7 ++++- .../license-eula-dialog.component.ts | 3 +- src/app/models/batch-software-license.ts | 1 + src/app/models/batch-software-skus.ts | 8 +++++ src/app/services/pricing.service.ts | 30 ++++++++++++++++--- src/app/services/pricing/pricing.model.ts | 12 +++++--- 6 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/app/models/batch-software-skus.ts diff --git a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts index 72b96e4804..316b357fb4 100644 --- a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts +++ b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts @@ -30,6 +30,10 @@ const softwares = [ id: "vray", description: "Chaos Group V-Ray", }, + { + id: "vrayrt", + description: "Chaos Group V-Ray RT", + }, ]; @Component({ @@ -132,9 +136,10 @@ export class AppLicensePickerComponent implements ControlValueAccessor, OnInit, private _updateLicenses() { this.licenses = List(softwares.map((software) => { const cost = this._pricing && this._pricing.get(software.id); + console.log("THIS IS COST: ", cost); let costStr = "-"; if (cost) { - const unit = cost.perCore ? "core" : "node"; + const unit = cost.theSku; costStr = `$${cost.price}/${unit}/hour`; } return new ApplicationLicense({ diff --git a/src/app/components/pool/action/add/license-eula-dialog/license-eula-dialog.component.ts b/src/app/components/pool/action/add/license-eula-dialog/license-eula-dialog.component.ts index d72baf88ea..0802dac43a 100644 --- a/src/app/components/pool/action/add/license-eula-dialog/license-eula-dialog.component.ts +++ b/src/app/components/pool/action/add/license-eula-dialog/license-eula-dialog.component.ts @@ -22,7 +22,8 @@ export class LicenseEulaDialogComponent { } public get isVray(): boolean { - return this.license && this.license.id === "vray"; + return this.license && (this.license.id === "vray" + || this.license.id === "vrayrt"); } public openLink(link: string) { diff --git a/src/app/models/batch-software-license.ts b/src/app/models/batch-software-license.ts index daf31d66f3..4a945bc39b 100644 --- a/src/app/models/batch-software-license.ts +++ b/src/app/models/batch-software-license.ts @@ -6,4 +6,5 @@ export enum BatchSoftwareLicense { arnold = "arnold", maya = "maya", vray = "vray", + vrayrt = "vrayrt", } diff --git a/src/app/models/batch-software-skus.ts b/src/app/models/batch-software-skus.ts new file mode 100644 index 0000000000..87aca6cd75 --- /dev/null +++ b/src/app/models/batch-software-skus.ts @@ -0,0 +1,8 @@ +/** + * List of SKUs for the software license pricing units + */ +export enum BatchSoftwareSkus { + core = "core", + gpu = "gpu", + node = "node", +} diff --git a/src/app/services/pricing.service.ts b/src/app/services/pricing.service.ts index 60e52d45f1..70b4a1132e 100644 --- a/src/app/services/pricing.service.ts +++ b/src/app/services/pricing.service.ts @@ -1,7 +1,7 @@ import { Injectable } from "@angular/core"; import { GlobalStorage } from "@batch-flask/core"; import { log } from "@batch-flask/utils"; -import { ArmBatchAccount, BatchSoftwareLicense, Pool, RateCardMeter } from "app/models"; +import { ArmBatchAccount, BatchSoftwareLicense, BatchSoftwareSkus, Pool, RateCardMeter } from "app/models"; import { BatchPricing, OSPricing, OsType, SoftwarePricing, VMPrices } from "app/services/pricing"; import { PoolPrice, PoolPriceOptions, PoolUtils } from "app/utils"; import { DateTime } from "luxon"; @@ -55,15 +55,17 @@ const regionMapping = { }; const softwareMeterId = { - "089f79d8-0349-432c-96a6-8add90b8a40e": BatchSoftwareLicense.arnold, + "da155550-4041-54ce-bf5c-385c0bd5eaba": BatchSoftwareLicense.arnold, "0ec88494-2022-4939-b809-0d914d954692": BatchSoftwareLicense["3dsmax"], "1d3bb602-0cde-4618-9fb0-f9d94805c2a6": BatchSoftwareLicense.maya, "e2d2d63e-8741-499a-8989-f5f7ec5c3b3f": BatchSoftwareLicense.vray, + "450f680c-b109-486a-8fec-2b9e7ab0fbc9": BatchSoftwareLicense.vrayrt, }; @Injectable({ providedIn: "root" }) export class PricingService { public pricing: Observable; + public theSku: string; private _pricingMap = new BehaviorSubject(null); constructor( @@ -81,6 +83,7 @@ export class PricingService { public getSoftwarePricing(): Observable { return this._getPrice((account, pricing) => { + console.log("PRICING FOR SOFTWARES: ", pricing.softwares); return pricing.softwares; }); } @@ -172,12 +175,30 @@ export class PricingService { return pricing; } + // IMPORTANT FOR PRICING CHANGES IN SOFTWARE private _processSoftwaresPricings(meters: RateCardMeter[], pricing: BatchPricing) { for (const meter of meters) { + // debugger; + // console.log("EACH METER: ", meter); if (meter.MeterId in softwareMeterId) { + console.log("meter.MeterId: ", meter.MeterId); const software = softwareMeterId[meter.MeterId]; - const perCore = meter.MeterName.toLowerCase().includes("1 vcpu"); - pricing.softwares.add(software, meter.MeterRates["0"], perCore); + console.log("THE SOFTWARE: ", software); + console.log("THE METER NAME: ", meter.MeterName); + // const perCore = meter.MeterName.toLowerCase().includes("1 vcpu"); + switch (meter.MeterName.toLowerCase()) { + case "1 vcpu": + this.theSku = BatchSoftwareSkus.core; + break; + case "1 gpu": + this.theSku = BatchSoftwareSkus.gpu; + break; + default: + this.theSku = BatchSoftwareSkus.node; + } + console.log("The CORE: ", this.theSku); + console.log("THIS IS THE PRICE: ", meter.MeterRates["0"]); + pricing.softwares.add(software, meter.MeterRates["0"], this.theSku); } } } @@ -230,6 +251,7 @@ export class PricingService { * @param callback Callback when account and prices are loaded */ private _getPrice(callback: (account: ArmBatchAccount, pricing: BatchPricing) => T) { + console.log("WHATS HERE? :", this.accountService.currentAccount); return this.accountService.currentAccount.pipe( take(1), flatMap((account) => { diff --git a/src/app/services/pricing/pricing.model.ts b/src/app/services/pricing/pricing.model.ts index b3cc7b4496..37be184355 100644 --- a/src/app/services/pricing/pricing.model.ts +++ b/src/app/services/pricing/pricing.model.ts @@ -1,3 +1,5 @@ +import { BatchSoftwareSkus } from "app/models/batch-software-skus"; + export type OsType = "linux" | "windows"; export interface RegionPrices { @@ -132,7 +134,7 @@ export class NodePricing { export interface SoftwarePrice { name: string; price: number; - perCore: boolean; + theSku: BatchSoftwareSkus; } export class SoftwarePricing { @@ -143,11 +145,11 @@ export class SoftwarePricing { } private _map: Map = new Map(); - public add(software: string, price: number, perCore = false) { + public add(software: string, price: number, theSku) { this._map.set(software, { name: software, price, - perCore, + theSku, }); } @@ -159,10 +161,12 @@ export class SoftwarePricing { return this._map.get(software); } + // TODO: test this to make sure data.theSku works with logic public getPrice(software: string, coreCount = 1): number { const data = this._map.get(software); if (!data) { return null; } - return data.perCore ? coreCount * data.price : data.price; + console.log("GET PRICE WHAT IS SKU FORMAT? :", data.theSku); + return data.theSku ? coreCount * data.price : data.price; } } From 0fe523c4a2dc62ecdeb3561bceabb411a3ad50b5 Mon Sep 17 00:00:00 2001 From: rechen Date: Fri, 8 May 2020 10:21:43 -0700 Subject: [PATCH 2/8] Added gpu to list of units * code clean up --- .../app-license-picker.component.ts | 4 +- src/app/models/index.ts | 1 + ...tware-skus.ts => software-billing-unit.ts} | 2 +- src/app/services/pricing.service.ts | 41 ++++++++----------- src/app/services/pricing/pricing.model.ts | 12 +++--- 5 files changed, 25 insertions(+), 35 deletions(-) rename src/app/models/{batch-software-skus.ts => software-billing-unit.ts} (77%) diff --git a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts index 316b357fb4..bbd8e0d7e1 100644 --- a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts +++ b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts @@ -136,11 +136,9 @@ export class AppLicensePickerComponent implements ControlValueAccessor, OnInit, private _updateLicenses() { this.licenses = List(softwares.map((software) => { const cost = this._pricing && this._pricing.get(software.id); - console.log("THIS IS COST: ", cost); let costStr = "-"; if (cost) { - const unit = cost.theSku; - costStr = `$${cost.price}/${unit}/hour`; + costStr = `$${cost.price}/${cost.billingUnit}/hour`; } return new ApplicationLicense({ ...software, diff --git a/src/app/models/index.ts b/src/app/models/index.ts index 89dd3ac689..70e95b4df8 100644 --- a/src/app/models/index.ts +++ b/src/app/models/index.ts @@ -14,6 +14,7 @@ export * from "./autoscale-formula"; export * from "./azure-batch"; export * from "./batch-account"; export * from "./batch-software-license"; +export * from "./software-billing-unit"; export * from "./blob-container"; export * from "./certificate-reference"; export * from "./certificate"; diff --git a/src/app/models/batch-software-skus.ts b/src/app/models/software-billing-unit.ts similarity index 77% rename from src/app/models/batch-software-skus.ts rename to src/app/models/software-billing-unit.ts index 87aca6cd75..98fdc2efc6 100644 --- a/src/app/models/batch-software-skus.ts +++ b/src/app/models/software-billing-unit.ts @@ -1,7 +1,7 @@ /** * List of SKUs for the software license pricing units */ -export enum BatchSoftwareSkus { +export enum SoftwareBillingUnit { core = "core", gpu = "gpu", node = "node", diff --git a/src/app/services/pricing.service.ts b/src/app/services/pricing.service.ts index 70b4a1132e..18744faade 100644 --- a/src/app/services/pricing.service.ts +++ b/src/app/services/pricing.service.ts @@ -1,7 +1,7 @@ import { Injectable } from "@angular/core"; import { GlobalStorage } from "@batch-flask/core"; import { log } from "@batch-flask/utils"; -import { ArmBatchAccount, BatchSoftwareLicense, BatchSoftwareSkus, Pool, RateCardMeter } from "app/models"; +import { ArmBatchAccount, BatchSoftwareLicense, Pool, RateCardMeter, SoftwareBillingUnit } from "app/models"; import { BatchPricing, OSPricing, OsType, SoftwarePricing, VMPrices } from "app/services/pricing"; import { PoolPrice, PoolPriceOptions, PoolUtils } from "app/utils"; import { DateTime } from "luxon"; @@ -65,7 +65,7 @@ const softwareMeterId = { @Injectable({ providedIn: "root" }) export class PricingService { public pricing: Observable; - public theSku: string; + public billingUnit: string; private _pricingMap = new BehaviorSubject(null); constructor( @@ -83,7 +83,6 @@ export class PricingService { public getSoftwarePricing(): Observable { return this._getPrice((account, pricing) => { - console.log("PRICING FOR SOFTWARES: ", pricing.softwares); return pricing.softwares; }); } @@ -175,34 +174,29 @@ export class PricingService { return pricing; } - // IMPORTANT FOR PRICING CHANGES IN SOFTWARE private _processSoftwaresPricings(meters: RateCardMeter[], pricing: BatchPricing) { for (const meter of meters) { - // debugger; - // console.log("EACH METER: ", meter); if (meter.MeterId in softwareMeterId) { - console.log("meter.MeterId: ", meter.MeterId); const software = softwareMeterId[meter.MeterId]; - console.log("THE SOFTWARE: ", software); - console.log("THE METER NAME: ", meter.MeterName); - // const perCore = meter.MeterName.toLowerCase().includes("1 vcpu"); - switch (meter.MeterName.toLowerCase()) { - case "1 vcpu": - this.theSku = BatchSoftwareSkus.core; - break; - case "1 gpu": - this.theSku = BatchSoftwareSkus.gpu; - break; - default: - this.theSku = BatchSoftwareSkus.node; - } - console.log("The CORE: ", this.theSku); - console.log("THIS IS THE PRICE: ", meter.MeterRates["0"]); - pricing.softwares.add(software, meter.MeterRates["0"], this.theSku); + this._setBillingUnit(meter); + pricing.softwares.add(software, meter.MeterRates["0"], this.billingUnit); } } } + private _setBillingUnit(meter: RateCardMeter) { + switch (meter.MeterName.toLowerCase()) { + case "1 vcpu vm license": + this.billingUnit = SoftwareBillingUnit.core; + break; + case "1 gpu vm license": + this.billingUnit = SoftwareBillingUnit.gpu; + break; + default: + this.billingUnit = SoftwareBillingUnit.node; + } + } + private _loadPricings() { this._loadPricingFromStorage().subscribe((map) => { if (map) { @@ -251,7 +245,6 @@ export class PricingService { * @param callback Callback when account and prices are loaded */ private _getPrice(callback: (account: ArmBatchAccount, pricing: BatchPricing) => T) { - console.log("WHATS HERE? :", this.accountService.currentAccount); return this.accountService.currentAccount.pipe( take(1), flatMap((account) => { diff --git a/src/app/services/pricing/pricing.model.ts b/src/app/services/pricing/pricing.model.ts index 37be184355..d3b2a586ad 100644 --- a/src/app/services/pricing/pricing.model.ts +++ b/src/app/services/pricing/pricing.model.ts @@ -1,4 +1,4 @@ -import { BatchSoftwareSkus } from "app/models/batch-software-skus"; +import { SoftwareBillingUnit } from "app/models/software-billing-unit"; export type OsType = "linux" | "windows"; @@ -134,7 +134,7 @@ export class NodePricing { export interface SoftwarePrice { name: string; price: number; - theSku: BatchSoftwareSkus; + billingUnit: SoftwareBillingUnit; } export class SoftwarePricing { @@ -145,11 +145,11 @@ export class SoftwarePricing { } private _map: Map = new Map(); - public add(software: string, price: number, theSku) { + public add(software: string, price: number, billingUnit) { this._map.set(software, { name: software, price, - theSku, + billingUnit, }); } @@ -161,12 +161,10 @@ export class SoftwarePricing { return this._map.get(software); } - // TODO: test this to make sure data.theSku works with logic public getPrice(software: string, coreCount = 1): number { const data = this._map.get(software); if (!data) { return null; } - console.log("GET PRICE WHAT IS SKU FORMAT? :", data.theSku); - return data.theSku ? coreCount * data.price : data.price; + return data.billingUnit === "core" ? coreCount * data.price : data.price; } } From 47df5b86c255f1430575545cacd5ee71c810d44c Mon Sep 17 00:00:00 2001 From: rechen Date: Fri, 8 May 2020 10:40:49 -0700 Subject: [PATCH 3/8] Added some function descriptions --- src/app/services/pricing.service.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/app/services/pricing.service.ts b/src/app/services/pricing.service.ts index 18744faade..9215b3b498 100644 --- a/src/app/services/pricing.service.ts +++ b/src/app/services/pricing.service.ts @@ -174,6 +174,11 @@ export class PricingService { return pricing; } + /** + * Sets the software prices using meter IDs + * @param meters RateCardMeter[] + * @param pricing BatchPricing + */ private _processSoftwaresPricings(meters: RateCardMeter[], pricing: BatchPricing) { for (const meter of meters) { if (meter.MeterId in softwareMeterId) { @@ -184,6 +189,10 @@ export class PricingService { } } + /** + * Sets billing unit of software prices + * @param meter RateCardMeter + */ private _setBillingUnit(meter: RateCardMeter) { switch (meter.MeterName.toLowerCase()) { case "1 vcpu vm license": From 920bea48aac67469bdf916c82fd16553333200b7 Mon Sep 17 00:00:00 2001 From: rechen Date: Fri, 8 May 2020 11:54:07 -0700 Subject: [PATCH 4/8] Added V-Ray RT to test cases and fixed pricing unit --- .../app-license-picker.component.spec.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts index 584ac8fcb8..7514dd1151 100644 --- a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts +++ b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts @@ -22,8 +22,8 @@ class TestComponent { } const pricing = new SoftwarePricing(); -pricing.add("maya", 12, false); -pricing.add("arnold", 5, true); +pricing.add("maya", 12, "node"); +pricing.add("arnold", 5, "node"); describe("AppLicensePickerComponent", () => { let fixture: ComponentFixture; @@ -64,30 +64,39 @@ describe("AppLicensePickerComponent", () => { fixture.detectChanges(); }); - it("Should show 4 licenses", () => { + it("Should show 5 licenses", () => { const tableRows = debugElement.queryAll(By.css("bl-row-render")); - expect(tableRows.length).toBe(4); + expect(tableRows.length).toBe(5); const row1Columns = tableRows[0].queryAll(By.css(".bl-table-cell")); expect(row1Columns.length).toBe(3, "Row has 3 columns"); + console.log("MAYA NAME: ", row1Columns[0].nativeElement.textContent); expect(row1Columns[0].nativeElement.textContent).toContain("Autodesk Maya"); + console.log("MAYA EULA: ", row1Columns[1].nativeElement.textContent); expect(row1Columns[1].nativeElement.textContent).toContain("EULA"); + console.log("MAYA PRICING: ", row1Columns[2].nativeElement.textContent); expect(row1Columns[2].nativeElement.textContent).toContain("$12/node/hour"); const row2Columns = tableRows[1].queryAll(By.css(".bl-table-cell")); expect(row2Columns[0].nativeElement.textContent).toContain("Autodesk 3ds Max"); expect(row2Columns[1].nativeElement.textContent).toContain("EULA"); + console.log("3DS PRICING: ", row2Columns[2].nativeElement.textContent); expect(row2Columns[2].nativeElement.textContent).toContain("-"); const row3Columns = tableRows[2].queryAll(By.css(".bl-table-cell")); expect(row3Columns[0].nativeElement.textContent).toContain("Autodesk Arnold"); expect(row3Columns[1].nativeElement.textContent).toContain("EULA"); - expect(row3Columns[2].nativeElement.textContent).toContain("$5/core/hour"); + expect(row3Columns[2].nativeElement.textContent).toContain("$5/node/hour"); const row4Columns = tableRows[3].queryAll(By.css(".bl-table-cell")); expect(row4Columns[0].nativeElement.textContent).toContain("Chaos Group V-Ray"); expect(row4Columns[1].nativeElement.textContent).toContain("EULA"); expect(row4Columns[2].nativeElement.textContent).toContain("-"); + + const row5Columns = tableRows[4].queryAll(By.css(".bl-table-cell")); + expect(row5Columns[0].nativeElement.textContent).toContain("Chaos Group V-Ray RT"); + expect(row5Columns[1].nativeElement.textContent).toContain("EULA"); + expect(row5Columns[2].nativeElement.textContent).toContain("-"); }); it("Should select license by checking checkbox", () => { From f264b99268d1b4a364c6d94631c0abf7ec041c94 Mon Sep 17 00:00:00 2001 From: rechen Date: Fri, 8 May 2020 14:29:31 -0700 Subject: [PATCH 5/8] Cleaned code and fixed tests in pools-utils --- .../app-license-picker/app-license-picker.component.spec.ts | 4 ---- src/app/utils/pool-utils.spec.ts | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts index 7514dd1151..8208ef921e 100644 --- a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts +++ b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts @@ -70,17 +70,13 @@ describe("AppLicensePickerComponent", () => { const row1Columns = tableRows[0].queryAll(By.css(".bl-table-cell")); expect(row1Columns.length).toBe(3, "Row has 3 columns"); - console.log("MAYA NAME: ", row1Columns[0].nativeElement.textContent); expect(row1Columns[0].nativeElement.textContent).toContain("Autodesk Maya"); - console.log("MAYA EULA: ", row1Columns[1].nativeElement.textContent); expect(row1Columns[1].nativeElement.textContent).toContain("EULA"); - console.log("MAYA PRICING: ", row1Columns[2].nativeElement.textContent); expect(row1Columns[2].nativeElement.textContent).toContain("$12/node/hour"); const row2Columns = tableRows[1].queryAll(By.css(".bl-table-cell")); expect(row2Columns[0].nativeElement.textContent).toContain("Autodesk 3ds Max"); expect(row2Columns[1].nativeElement.textContent).toContain("EULA"); - console.log("3DS PRICING: ", row2Columns[2].nativeElement.textContent); expect(row2Columns[2].nativeElement.textContent).toContain("-"); const row3Columns = tableRows[2].queryAll(By.css(".bl-table-cell")); diff --git a/src/app/utils/pool-utils.spec.ts b/src/app/utils/pool-utils.spec.ts index 75f2989701..4e833d5485 100644 --- a/src/app/utils/pool-utils.spec.ts +++ b/src/app/utils/pool-utils.spec.ts @@ -183,9 +183,9 @@ describe("PoolUtils", () => { } as any); const softwares = new SoftwarePricing(); - softwares.add("vray", 0.02, true); - softwares.add("3dsmax", 0.65, false); - softwares.add("maya", 0.75, false); + softwares.add("vray", 0.02, "core"); + softwares.add("3dsmax", 0.65, "node"); + softwares.add("maya", 0.75, "node"); it("works for a basic pool", () => { const windowsConfig = { From d884642dde865cbfabce902de91f5c7f5849f5ea Mon Sep 17 00:00:00 2001 From: rechen Date: Mon, 18 May 2020 16:27:04 -0700 Subject: [PATCH 6/8] Updated billingUnit type to SoftwareBillingUnit * Minor updates --- .../app-license-picker.component.spec.ts | 5 +++-- .../add/app-license-picker/app-license-picker.component.ts | 2 +- src/app/models/software-billing-unit.ts | 2 +- src/app/services/pricing.service.ts | 2 +- src/app/services/pricing/pricing.model.ts | 2 +- src/app/utils/pool-utils.spec.ts | 7 ++++--- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts index 8208ef921e..55207eca39 100644 --- a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts +++ b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.spec.ts @@ -10,6 +10,7 @@ import { ElectronTestingModule } from "@batch-flask/electron/testing"; import { BreadcrumbService } from "@batch-flask/ui/breadcrumbs"; import { TableTestingModule } from "@batch-flask/ui/testing"; import { AppLicensePickerComponent } from "app/components/pool/action/add"; +import { SoftwareBillingUnit } from "app/models"; import { PricingService } from "app/services"; import { SoftwarePricing } from "app/services/pricing"; import { of } from "rxjs"; @@ -22,8 +23,8 @@ class TestComponent { } const pricing = new SoftwarePricing(); -pricing.add("maya", 12, "node"); -pricing.add("arnold", 5, "node"); +pricing.add("maya", 12, SoftwareBillingUnit.node); +pricing.add("arnold", 5, SoftwareBillingUnit.node); describe("AppLicensePickerComponent", () => { let fixture: ComponentFixture; diff --git a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts index bbd8e0d7e1..32979caf8a 100644 --- a/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts +++ b/src/app/components/pool/action/add/app-license-picker/app-license-picker.component.ts @@ -138,7 +138,7 @@ export class AppLicensePickerComponent implements ControlValueAccessor, OnInit, const cost = this._pricing && this._pricing.get(software.id); let costStr = "-"; if (cost) { - costStr = `$${cost.price}/${cost.billingUnit}/hour`; + costStr = `$${cost.price}/${cost.billingUnit as string}/hour`; } return new ApplicationLicense({ ...software, diff --git a/src/app/models/software-billing-unit.ts b/src/app/models/software-billing-unit.ts index 98fdc2efc6..80df7e0b98 100644 --- a/src/app/models/software-billing-unit.ts +++ b/src/app/models/software-billing-unit.ts @@ -1,5 +1,5 @@ /** - * List of SKUs for the software license pricing units + * List of pricing units for software licenses */ export enum SoftwareBillingUnit { core = "core", diff --git a/src/app/services/pricing.service.ts b/src/app/services/pricing.service.ts index 9215b3b498..aaa25798b3 100644 --- a/src/app/services/pricing.service.ts +++ b/src/app/services/pricing.service.ts @@ -65,7 +65,7 @@ const softwareMeterId = { @Injectable({ providedIn: "root" }) export class PricingService { public pricing: Observable; - public billingUnit: string; + public billingUnit: SoftwareBillingUnit; private _pricingMap = new BehaviorSubject(null); constructor( diff --git a/src/app/services/pricing/pricing.model.ts b/src/app/services/pricing/pricing.model.ts index d3b2a586ad..d3bd9abb37 100644 --- a/src/app/services/pricing/pricing.model.ts +++ b/src/app/services/pricing/pricing.model.ts @@ -145,7 +145,7 @@ export class SoftwarePricing { } private _map: Map = new Map(); - public add(software: string, price: number, billingUnit) { + public add(software: string, price: number, billingUnit: SoftwareBillingUnit) { this._map.set(software, { name: software, price, diff --git a/src/app/utils/pool-utils.spec.ts b/src/app/utils/pool-utils.spec.ts index 4e833d5485..7950c3c523 100644 --- a/src/app/utils/pool-utils.spec.ts +++ b/src/app/utils/pool-utils.spec.ts @@ -1,6 +1,7 @@ import { CloudServiceOsFamily, Pool, VmSize } from "app/models"; import { SoftwarePricing } from "app/services/pricing"; import { PoolUtils } from "app/utils"; +import { SoftwareBillingUnit } from "app/models"; describe("PoolUtils", () => { describe("#getOsName()", () => { @@ -183,9 +184,9 @@ describe("PoolUtils", () => { } as any); const softwares = new SoftwarePricing(); - softwares.add("vray", 0.02, "core"); - softwares.add("3dsmax", 0.65, "node"); - softwares.add("maya", 0.75, "node"); + softwares.add("vray", 0.02, SoftwareBillingUnit.core); + softwares.add("3dsmax", 0.65, SoftwareBillingUnit.node); + softwares.add("maya", 0.75, SoftwareBillingUnit.node); it("works for a basic pool", () => { const windowsConfig = { From 0a397e6570cb12fff76acf841293a449bca3b686 Mon Sep 17 00:00:00 2001 From: rechen Date: Tue, 19 May 2020 10:39:50 -0700 Subject: [PATCH 7/8] Minor linting fixes --- src/app/utils/pool-utils.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app/utils/pool-utils.spec.ts b/src/app/utils/pool-utils.spec.ts index 7950c3c523..b9f3b3d4b0 100644 --- a/src/app/utils/pool-utils.spec.ts +++ b/src/app/utils/pool-utils.spec.ts @@ -1,7 +1,6 @@ -import { CloudServiceOsFamily, Pool, VmSize } from "app/models"; +import { CloudServiceOsFamily, Pool, SoftwareBillingUnit, VmSize } from "app/models"; import { SoftwarePricing } from "app/services/pricing"; import { PoolUtils } from "app/utils"; -import { SoftwareBillingUnit } from "app/models"; describe("PoolUtils", () => { describe("#getOsName()", () => { From ad3a174d60d137bd58291a1f732d5703e6412010 Mon Sep 17 00:00:00 2001 From: rechen Date: Tue, 19 May 2020 15:37:11 -0700 Subject: [PATCH 8/8] Updated billingUnit within softwareMeterId mapping --- src/app/services/pricing.service.ts | 49 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/app/services/pricing.service.ts b/src/app/services/pricing.service.ts index aaa25798b3..c23db1a1bb 100644 --- a/src/app/services/pricing.service.ts +++ b/src/app/services/pricing.service.ts @@ -55,17 +55,31 @@ const regionMapping = { }; const softwareMeterId = { - "da155550-4041-54ce-bf5c-385c0bd5eaba": BatchSoftwareLicense.arnold, - "0ec88494-2022-4939-b809-0d914d954692": BatchSoftwareLicense["3dsmax"], - "1d3bb602-0cde-4618-9fb0-f9d94805c2a6": BatchSoftwareLicense.maya, - "e2d2d63e-8741-499a-8989-f5f7ec5c3b3f": BatchSoftwareLicense.vray, - "450f680c-b109-486a-8fec-2b9e7ab0fbc9": BatchSoftwareLicense.vrayrt, + "da155550-4041-54ce-bf5c-385c0bd5eaba": { + license: BatchSoftwareLicense.arnold, + billingUnit: SoftwareBillingUnit.node, + }, + "0ec88494-2022-4939-b809-0d914d954692": { + license: BatchSoftwareLicense["3dsmax"], + billingUnit: SoftwareBillingUnit.node, + }, + "1d3bb602-0cde-4618-9fb0-f9d94805c2a6": { + license: BatchSoftwareLicense.maya, + billingUnit: SoftwareBillingUnit.node, + }, + "e2d2d63e-8741-499a-8989-f5f7ec5c3b3f": { + license: BatchSoftwareLicense.vray, + billingUnit: SoftwareBillingUnit.core, + }, + "450f680c-b109-486a-8fec-2b9e7ab0fbc9": { + license: BatchSoftwareLicense.vrayrt, + billingUnit: SoftwareBillingUnit.gpu, + }, }; @Injectable({ providedIn: "root" }) export class PricingService { public pricing: Observable; - public billingUnit: SoftwareBillingUnit; private _pricingMap = new BehaviorSubject(null); constructor( @@ -182,30 +196,13 @@ export class PricingService { private _processSoftwaresPricings(meters: RateCardMeter[], pricing: BatchPricing) { for (const meter of meters) { if (meter.MeterId in softwareMeterId) { - const software = softwareMeterId[meter.MeterId]; - this._setBillingUnit(meter); - pricing.softwares.add(software, meter.MeterRates["0"], this.billingUnit); + const software = softwareMeterId[meter.MeterId].license; + const unit = softwareMeterId[meter.MeterId].billingUnit; + pricing.softwares.add(software, meter.MeterRates["0"], unit); } } } - /** - * Sets billing unit of software prices - * @param meter RateCardMeter - */ - private _setBillingUnit(meter: RateCardMeter) { - switch (meter.MeterName.toLowerCase()) { - case "1 vcpu vm license": - this.billingUnit = SoftwareBillingUnit.core; - break; - case "1 gpu vm license": - this.billingUnit = SoftwareBillingUnit.gpu; - break; - default: - this.billingUnit = SoftwareBillingUnit.node; - } - } - private _loadPricings() { this._loadPricingFromStorage().subscribe((map) => { if (map) {