From 324d65aa2b979c08dda0fd7924f7fbb88dcf5d2f Mon Sep 17 00:00:00 2001 From: Akiomi Kamakura Date: Fri, 10 Dec 2021 17:09:06 +0900 Subject: [PATCH 1/4] Add force ondemand api mode --- src/custom-functions/v3/bcode-daily.test.ts | 2 +- src/custom-functions/v3/bcode-daily.ts | 5 ++-- src/custom-functions/v3/bcode-quarter.test.ts | 2 +- src/custom-functions/v3/bcode-quarter.ts | 5 ++-- src/custom-functions/v3/bcode.ts | 18 +++++++++++++-- src/services/csv-exporter.ts | 11 +++++++-- src/setting.test.ts | 16 +++++++++---- src/setting.ts | 23 ++++++++++++++++--- src/ui/setting-sidebar.html | 18 ++++++++++++--- src/ui/setting-sidebar.ts | 3 ++- 10 files changed, 82 insertions(+), 21 deletions(-) diff --git a/src/custom-functions/v3/bcode-daily.test.ts b/src/custom-functions/v3/bcode-daily.test.ts index a0977a7..ba4a6b3 100644 --- a/src/custom-functions/v3/bcode-daily.test.ts +++ b/src/custom-functions/v3/bcode-daily.test.ts @@ -16,7 +16,7 @@ test('bcodeDaily', () => { expect(DailyCache.get(ticker, date)).toBeNull() const client = new CachingBuffettCodeApiClientV3('token') - const result = bcodeDaily(client, ticker, date, propertyName, false) + const result = bcodeDaily(client, ticker, date, propertyName, false, false) expect(result).toEqual(new BcodeResult(propertyName, 550294097166, '円')) expect(DailyCache.get(ticker, date)).not.toBeNull() diff --git a/src/custom-functions/v3/bcode-daily.ts b/src/custom-functions/v3/bcode-daily.ts index 8859374..8f49559 100644 --- a/src/custom-functions/v3/bcode-daily.ts +++ b/src/custom-functions/v3/bcode-daily.ts @@ -15,7 +15,8 @@ export function bcodeDaily( ticker: string, date: DateParam, propertyName: string, - ondemandApiEnabled: boolean + ondemandApiEnabled: boolean, + forceOndemandApiEnabled: boolean ): BcodeResult { const companyService = new CompanyService(ticker, client) if (!companyService.isSupportedTicker()) { @@ -23,7 +24,7 @@ export function bcodeDaily( } let daily: Daily - if (companyService.isOndemandDailyApiPeriod(date)) { + if (forceOndemandApiEnabled || companyService.isOndemandDailyApiPeriod(date)) { if (!ondemandApiEnabled) { throw new OndemandApiNotEnabledError() } diff --git a/src/custom-functions/v3/bcode-quarter.test.ts b/src/custom-functions/v3/bcode-quarter.test.ts index 56f8b6a..c35b598 100644 --- a/src/custom-functions/v3/bcode-quarter.test.ts +++ b/src/custom-functions/v3/bcode-quarter.test.ts @@ -17,7 +17,7 @@ test('bcodeQuarter', () => { expect(QuarterCache.get(ticker, period)).toBeNull() const client = new CachingBuffettCodeApiClientV3('token') - const result = bcodeQuarter(client, ticker, YearQuarterParam.fromYearQuarter(period), propertyName, false) + const result = bcodeQuarter(client, ticker, YearQuarterParam.fromYearQuarter(period), propertyName, false, false) expect(result).toEqual(new BcodeResult(propertyName, 12513000000, '円')) expect(QuarterCache.get(ticker, period)).not.toBeNull() diff --git a/src/custom-functions/v3/bcode-quarter.ts b/src/custom-functions/v3/bcode-quarter.ts index 1f92dec..3e6faf1 100644 --- a/src/custom-functions/v3/bcode-quarter.ts +++ b/src/custom-functions/v3/bcode-quarter.ts @@ -15,7 +15,8 @@ export function bcodeQuarter( ticker: string, period: YearQuarterParam, propertyName: string, - ondemandApiEnabled: boolean + ondemandApiEnabled: boolean, + forceOndemandApiEnabled: boolean ): BcodeResult { const companyService = new CompanyService(ticker, client) if (!companyService.isSupportedTicker()) { @@ -23,7 +24,7 @@ export function bcodeQuarter( } let quarter: Quarter - if (companyService.isOndemandQuarterApiPeriod(period)) { + if (forceOndemandApiEnabled || companyService.isOndemandQuarterApiPeriod(period)) { if (!ondemandApiEnabled) { throw new OndemandApiNotEnabledError() } diff --git a/src/custom-functions/v3/bcode.ts b/src/custom-functions/v3/bcode.ts index b9acc96..87f0b1d 100644 --- a/src/custom-functions/v3/bcode.ts +++ b/src/custom-functions/v3/bcode.ts @@ -78,9 +78,23 @@ export function bcode( const parsedPeriod = PeriodParser.parse(period) let result: BcodeResult if (parsedPeriod instanceof DateParam) { - result = bcodeDaily(client, ticker, parsedPeriod, propertyName, setting.ondemandApiEnabled) + result = bcodeDaily( + client, + ticker, + parsedPeriod, + propertyName, + setting.ondemandApiEnabled, + setting.forceOndemandApiEnabled + ) } else { - result = bcodeQuarter(client, ticker, parsedPeriod, propertyName, setting.ondemandApiEnabled) + result = bcodeQuarter( + client, + ticker, + parsedPeriod, + propertyName, + setting.ondemandApiEnabled, + setting.forceOndemandApiEnabled + ) } return result.format(isRawValue, isWithUnits) diff --git a/src/services/csv-exporter.ts b/src/services/csv-exporter.ts index 3f7d44c..58635ee 100644 --- a/src/services/csv-exporter.ts +++ b/src/services/csv-exporter.ts @@ -35,8 +35,15 @@ export class CsvExporter { const ondemandQuarterApiPeriodRange = new OndemandApiPeriodRange(companyService) - const ondemandQuarterApiPeriods = ondemandQuarterApiPeriodRange.selectOndemandQuarterApiPeriod(ticker, range) - const quarterApiPeriods = ondemandQuarterApiPeriodRange.filterOndemandQuarterApiPeriod(ticker, range) + let ondemandQuarterApiPeriods = [] + let quarterApiPeriods = [] + + if (setting.forceOndemandApiEnabled) { + ondemandQuarterApiPeriods = range.range() + } else { + ondemandQuarterApiPeriods = ondemandQuarterApiPeriodRange.selectOndemandQuarterApiPeriod(ticker, range) + quarterApiPeriods = ondemandQuarterApiPeriodRange.filterOndemandQuarterApiPeriod(ticker, range) + } if (ondemandQuarterApiPeriods.length > 0 && !setting.ondemandApiEnabled) { throw new Error( diff --git a/src/setting.test.ts b/src/setting.test.ts index f80c815..a6fb72d 100644 --- a/src/setting.test.ts +++ b/src/setting.test.ts @@ -5,7 +5,10 @@ declare const global: any test('load', () => { const mockGetProperty = jest.fn() - mockGetProperty.mockReturnValueOnce('foo').mockReturnValueOnce('true') + mockGetProperty + .mockReturnValueOnce('foo') + .mockReturnValueOnce('true') + .mockReturnValueOnce('true') global.PropertiesService = { getUserProperties: (): object => { @@ -16,9 +19,10 @@ test('load', () => { } const setting = Setting.load() - expect(mockGetProperty.mock.calls.length).toBe(2) + expect(mockGetProperty.mock.calls.length).toBe(3) expect(setting.token).toBe('foo') expect(setting.ondemandApiEnabled).toBe(true) + expect(setting.forceOndemandApiEnabled).toBe(true) }) test('load__ondemandApiEnabledCasting', () => { @@ -53,11 +57,13 @@ test('save', () => { const setting = Setting.load() setting.token = 'bar' setting.ondemandApiEnabled = true + setting.forceOndemandApiEnabled = true setting.save() - expect(mockSetProperty.mock.calls.length).toBe(2) + expect(mockSetProperty.mock.calls.length).toBe(3) expect(mockSetProperty.mock.calls[0]).toEqual([Setting.tokenProperty, 'bar']) expect(mockSetProperty.mock.calls[1]).toEqual([Setting.ondemandApiEnabledProperty, true]) + expect(mockSetProperty.mock.calls[2]).toEqual([Setting.forceOndemandApiEnabledProperty, true]) }) test('setDefaultToken', () => { @@ -94,9 +100,11 @@ test('toObject', () => { const setting = Setting.load() setting.setDefaultToken() setting.setDefaultOndemandApiEnabled() + setting.setDefaultForceOndemandApiEnabled() expect(setting.toObject()).toStrictEqual({ token: Setting.defaultToken, - ondemandApiEnabled: Setting.defaultOndemandApiEnabled + ondemandApiEnabled: Setting.defaultOndemandApiEnabled, + forceOndemandApiEnabled: Setting.defaultForceOndemandApiEnabled }) }) diff --git a/src/setting.ts b/src/setting.ts index 4f438ac..a0b4f37 100644 --- a/src/setting.ts +++ b/src/setting.ts @@ -1,10 +1,12 @@ export class Setting { static readonly tokenProperty = 'token' static readonly ondemandApiEnabledProperty = 'ondemand-api-enabled' + static readonly forceOndemandApiEnabledProperty = 'force-ondemand-api-enabled' static readonly defaultToken = 'sAJGq9JH193KiwnF947v74KnDYkO7z634LWQQfPY' static readonly defaultOndemandApiEnabled = false + static readonly defaultForceOndemandApiEnabled = false - private constructor(private _token, private _ondemandApiEnabled) {} + private constructor(private _token, private _ondemandApiEnabled, private _forceOndemandApiEnabled) {} public get token(): string { return this._token @@ -22,6 +24,14 @@ export class Setting { this._ondemandApiEnabled = ondemandApiEnabled } + public get forceOndemandApiEnabled(): boolean { + return this._forceOndemandApiEnabled + } + + public set forceOndemandApiEnabled(forceOndemandApiEnabled: boolean) { + this._forceOndemandApiEnabled = forceOndemandApiEnabled + } + public setDefaultToken(): void { this._token = Setting.defaultToken } @@ -30,10 +40,15 @@ export class Setting { this._ondemandApiEnabled = Setting.defaultOndemandApiEnabled } + public setDefaultForceOndemandApiEnabled(): void { + this._forceOndemandApiEnabled = Setting.defaultForceOndemandApiEnabled + } + public toObject(): object { return { token: this.token, - ondemandApiEnabled: this.ondemandApiEnabled + ondemandApiEnabled: this.ondemandApiEnabled, + forceOndemandApiEnabled: this.forceOndemandApiEnabled } } @@ -41,13 +56,15 @@ export class Setting { const props = PropertiesService.getUserProperties() props.setProperty(Setting.tokenProperty, this._token) props.setProperty(Setting.ondemandApiEnabledProperty, this._ondemandApiEnabled) + props.setProperty(Setting.forceOndemandApiEnabledProperty, this._forceOndemandApiEnabled) } public static load(): Setting { const props = PropertiesService.getUserProperties() const token = props.getProperty(this.tokenProperty) const ondemandApiEnabled = props.getProperty(this.ondemandApiEnabledProperty) == 'true' - const setting = new Setting(token, ondemandApiEnabled) + const forceOndemandApiEnabled = props.getProperty(this.forceOndemandApiEnabledProperty) == 'true' + const setting = new Setting(token, ondemandApiEnabled, forceOndemandApiEnabled) return setting } } diff --git a/src/ui/setting-sidebar.html b/src/ui/setting-sidebar.html index acae3b3..253b2b7 100644 --- a/src/ui/setting-sidebar.html +++ b/src/ui/setting-sidebar.html @@ -24,6 +24,9 @@ if (setting.ondemandApiEnabled) { document.getElementById('ondemand-api-check').checked = setting.ondemandApiEnabled } + if (setting.forceOndemandApiEnabled) { + document.getElementById('force-ondemand-api-check').checked = setting.forceOndemandApiEnabled + } }) .loadSetting() } @@ -31,6 +34,7 @@ function saveSetting() { const token = document.getElementById('token-input').value const ondemandApiEnabled = document.getElementById('ondemand-api-check').checked + const forceOndemandApiEnabled = document.getElementById('force-ondemand-api-check').checked google.script.run .withFailureHandler(onSaveSettingError) @@ -38,7 +42,7 @@ alert('設定を保存しました') google.script.host.close() }) - .saveSetting(token, ondemandApiEnabled) + .saveSetting(token, ondemandApiEnabled, forceOndemandApiEnabled) } @@ -76,8 +80,16 @@

■注意事項

- - +
diff --git a/src/ui/setting-sidebar.ts b/src/ui/setting-sidebar.ts index eb5fd01..4e0ad60 100644 --- a/src/ui/setting-sidebar.ts +++ b/src/ui/setting-sidebar.ts @@ -4,9 +4,10 @@ export function loadSetting(): object { return Setting.load().toObject() } -export function saveSetting(token: string, ondemandApiEnabled: boolean): void { +export function saveSetting(token: string, ondemandApiEnabled: boolean, forceOndemandApiEnabled: boolean): void { const setting = Setting.load() setting.token = token setting.ondemandApiEnabled = ondemandApiEnabled + setting.forceOndemandApiEnabled = forceOndemandApiEnabled setting.save() } From be61bb517965308ae51a50fec63329904c8ad3a1 Mon Sep 17 00:00:00 2001 From: Akiomi Kamakura Date: Fri, 14 Jan 2022 15:08:28 +0900 Subject: [PATCH 2/4] Add forceOndemandApiEnabled validation --- src/setting.test.ts | 56 +++++++++++++++++++++++++++++++++++++ src/setting.ts | 12 ++++++++ src/ui/setting-sidebar.html | 26 +++++++++++++++-- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/setting.test.ts b/src/setting.test.ts index a6fb72d..a3a3a65 100644 --- a/src/setting.test.ts +++ b/src/setting.test.ts @@ -41,6 +41,42 @@ test('load__ondemandApiEnabledCasting', () => { expect(setting.ondemandApiEnabled).toBe(false) }) +test('isValid (true)', () => { + const mockGetProperty = jest.fn() + + global.PropertiesService = { + getUserProperties: (): object => { + return { + getProperty: mockGetProperty + } + } + } + + const setting = Setting.load() + setting.token = 'bar' + setting.ondemandApiEnabled = true + setting.forceOndemandApiEnabled = false + expect(setting.isValid()).toBeTruthy() +}) + +test('isValid (false)', () => { + const mockGetProperty = jest.fn() + + global.PropertiesService = { + getUserProperties: (): object => { + return { + getProperty: mockGetProperty + } + } + } + + const setting = Setting.load() + setting.token = 'bar' + setting.ondemandApiEnabled = false + setting.forceOndemandApiEnabled = true + expect(setting.isValid()).toBeFalsy() +}) + test('save', () => { const mockGetProperty = jest.fn() const mockSetProperty = jest.fn() @@ -66,6 +102,26 @@ test('save', () => { expect(mockSetProperty.mock.calls[2]).toEqual([Setting.forceOndemandApiEnabledProperty, true]) }) +test('save (ondemandApiEnabled is false but forceOndemandApiEnabled is true)', () => { + const mockGetProperty = jest.fn() + const mockSetProperty = jest.fn() + + global.PropertiesService = { + getUserProperties: (): object => { + return { + getProperty: mockGetProperty, + setProperty: mockSetProperty + } + } + } + + const setting = Setting.load() + setting.token = 'bar' + setting.ondemandApiEnabled = false + setting.forceOndemandApiEnabled = true + expect(() => setting.save()).toThrow(Error) +}) + test('setDefaultToken', () => { const mockGetProperty = jest.fn() mockGetProperty.mockReturnValue(undefined) diff --git a/src/setting.ts b/src/setting.ts index a0b4f37..d22b64d 100644 --- a/src/setting.ts +++ b/src/setting.ts @@ -52,7 +52,19 @@ export class Setting { } } + public isValid(): boolean { + if (!this._ondemandApiEnabled && this._forceOndemandApiEnabled) { + return false + } + + return true + } + public save(): void { + if (!this.isValid()) { + throw new Error('Setting is invalid state') + } + const props = PropertiesService.getUserProperties() props.setProperty(Setting.tokenProperty, this._token) props.setProperty(Setting.ondemandApiEnabledProperty, this._ondemandApiEnabled) diff --git a/src/ui/setting-sidebar.html b/src/ui/setting-sidebar.html index 253b2b7..77497df 100644 --- a/src/ui/setting-sidebar.html +++ b/src/ui/setting-sidebar.html @@ -3,6 +3,11 @@ + @@ -80,14 +100,14 @@

■注意事項

-