From 7324005c88a378f69f2a999f3f4440ffba3fac88 Mon Sep 17 00:00:00 2001 From: Akiomi Kamakura Date: Wed, 8 Dec 2021 10:54:52 +0900 Subject: [PATCH 1/2] Improve entities --- src/entities/v3/daily.test.ts | 24 +++++++++++++++++++++ src/entities/v3/daily.ts | 34 ++++++++++++++++++++++++++++- src/entities/v3/interface.ts | 11 ++++++++++ src/entities/v3/quarter.test.ts | 25 ++++++++++++++++++++++ src/entities/v3/quarter.ts | 38 ++++++++++++++++++++++++++++++++- 5 files changed, 130 insertions(+), 2 deletions(-) create mode 100644 src/entities/v3/daily.test.ts create mode 100644 src/entities/v3/interface.ts create mode 100644 src/entities/v3/quarter.test.ts diff --git a/src/entities/v3/daily.test.ts b/src/entities/v3/daily.test.ts new file mode 100644 index 0000000..1f9d1c3 --- /dev/null +++ b/src/entities/v3/daily.test.ts @@ -0,0 +1,24 @@ +import * as response from '~/__mocks__/fixtures/v3/daily' +import { Daily } from '~/entities/v3/daily' + +const daily = Daily.fromResponse(response) + +test('period', () => { + expect(daily.period()).toEqual(new Date('2020-09-06')) +}) + +test('propertyNames', () => { + expect(daily.propertyNames()).toEqual( + Object.keys(response['column_description']) + ) +}) + +test('labelOf', () => { + expect(daily.labelOf('day')).toEqual('日付') + expect(daily.labelOf('market_capital')).toEqual('時価総額') +}) + +test('unitOf', () => { + expect(daily.unitOf('day')).toEqual('単位無し') + expect(daily.unitOf('market_capital')).toEqual('円') +}) diff --git a/src/entities/v3/daily.ts b/src/entities/v3/daily.ts index 0f71817..cef71d6 100644 --- a/src/entities/v3/daily.ts +++ b/src/entities/v3/daily.ts @@ -1,8 +1,40 @@ -export class Daily { +import { HasColumnDescription, HasPeriod } from '~/entities/v3/interface' + +export class Daily implements HasColumnDescription, HasPeriod { constructor(readonly data: object, readonly columnDescription: object) { // noop } + period(): Date { + return new Date(this.data['day']) + } + + propertyNames(): string[] { + return Object.keys(this.columnDescription) + } + + labelOf(propertyName: string): string | null { + const desc = this.columnDescriptionOf(propertyName) + if (desc) { + return desc['name_jp'] + } else { + return null + } + } + + unitOf(propertyName: string): string | null { + const desc = this.columnDescriptionOf(propertyName) + if (desc) { + return desc['unit'] + } else { + return null + } + } + + private columnDescriptionOf(propertyName: string): string | null { + return this.columnDescription[propertyName] + } + static fromResponse(response: object): Daily { return new Daily(response['data'], response['column_description']) } diff --git a/src/entities/v3/interface.ts b/src/entities/v3/interface.ts new file mode 100644 index 0000000..a339a69 --- /dev/null +++ b/src/entities/v3/interface.ts @@ -0,0 +1,11 @@ +export interface HasColumnDescription { + propertyNames(): string[] + + labelOf(propertyName: string): string | null + + unitOf(propertyName: string): string | null +} + +export interface HasPeriod { + period(): T +} diff --git a/src/entities/v3/quarter.test.ts b/src/entities/v3/quarter.test.ts new file mode 100644 index 0000000..a806aea --- /dev/null +++ b/src/entities/v3/quarter.test.ts @@ -0,0 +1,25 @@ +import * as response from '~/__mocks__/fixtures/v3/quarter' +import { Quarter } from '~/entities/v3/quarter' +import { YearQuarter } from '~/fiscal-periods/year-quarter' + +const quarter = Quarter.fromResponse(response) + +test('period', () => { + expect(quarter.period()).toEqual(new YearQuarter(2018, 1)) +}) + +test('propertyNames', () => { + expect(quarter.propertyNames()).toEqual( + Object.keys(response['column_description']) + ) +}) + +test('labelOf', () => { + expect(quarter.labelOf('fiscal_year')).toEqual('会計年度') + expect(quarter.labelOf('net_sales')).toEqual('売上') +}) + +test('unitOf', () => { + expect(quarter.unitOf('fiscal_year')).toEqual('なし') + expect(quarter.unitOf('net_sales')).toEqual('円') +}) diff --git a/src/entities/v3/quarter.ts b/src/entities/v3/quarter.ts index 51f90f5..f98031e 100644 --- a/src/entities/v3/quarter.ts +++ b/src/entities/v3/quarter.ts @@ -1,8 +1,44 @@ -export class Quarter { +import { HasColumnDescription, HasPeriod } from '~/entities/v3/interface' +import { YearQuarter } from '~/fiscal-periods/year-quarter' + +export class Quarter implements HasColumnDescription, HasPeriod { constructor(readonly data: object, readonly columnDescription: object) { // noop } + period(): YearQuarter { + return new YearQuarter( + this.data['fiscal_year'], + this.data['fiscal_quarter'] + ) + } + + propertyNames(): string[] { + return Object.keys(this.columnDescription) + } + + labelOf(propertyName: string): string | null { + const desc = this.columnDescriptionOf(propertyName) + if (desc) { + return desc['name_jp'] + } else { + return null + } + } + + unitOf(propertyName: string): string | null { + const desc = this.columnDescriptionOf(propertyName) + if (desc) { + return desc['unit'] + } else { + return null + } + } + + private columnDescriptionOf(propertyName: string): string | null { + return this.columnDescription[propertyName] + } + static fromResponse(response: object): Quarter { return new Quarter(response['data'], response['column_description']) } From 42f24e921e7d531bfd7b42d07ad28255224f1c65 Mon Sep 17 00:00:00 2001 From: Akiomi Kamakura Date: Wed, 8 Dec 2021 10:56:15 +0900 Subject: [PATCH 2/2] Use v3 endpoint in csv exporter --- src/services/csv-exporter.test.ts | 20 +++++++++----------- src/services/csv-exporter.ts | 25 ++++++++++--------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/services/csv-exporter.test.ts b/src/services/csv-exporter.test.ts index fa5a316..908a8dd 100644 --- a/src/services/csv-exporter.test.ts +++ b/src/services/csv-exporter.test.ts @@ -1,15 +1,11 @@ -import { default as quarter } from '~/__mocks__/fixtures/v2/quarter-property' -import { QuarterProperty } from '~/api/v2/quarter-property' +import { default as quarter } from '~/__mocks__/fixtures/v3/quarter' import { YearQuarter } from '~/fiscal-periods/year-quarter' import { CsvExporter } from '~/services/csv-exporter' import { QuarterCache } from '~/services/quarter-cache' jest.mock('~/setting', () => jest.requireActual('~/__mocks__/setting')) -jest.mock('~/api/v2/client', () => - jest.requireActual('~/__mocks__/api/v2/client') -) -jest.mock('~/api/v2/quarter-property', () => - jest.requireActual('~/__mocks__/api/v2/quarter-property') +jest.mock('~/api/v3/client', () => + jest.requireActual('~/__mocks__/api/v3/client') ) jest.mock('~/services/quarter-property-cache', () => jest.requireActual('~/__mocks__/services/quarter-property-cache') @@ -21,8 +17,10 @@ jest.mock('~/services/quarter-cache', () => jest.requireActual('~/__mocks__/services/quarter-cache') ) -const fiscalYearIndex = Object.keys(quarter).indexOf('fiscal_year') -const fiscalQuarterIndex = Object.keys(quarter).indexOf('fiscal_quarter') +const columnDescription = quarter['column_description'] +const propertyNames = Object.keys(columnDescription) +const fiscalYearIndex = propertyNames.indexOf('fiscal_year') +const fiscalQuarterIndex = propertyNames.indexOf('fiscal_quarter') describe('generateData', () => { test('uncached', () => { @@ -34,7 +32,7 @@ describe('generateData', () => { const data = CsvExporter.generateData(ticker, from, to, today) - expect(data.length).toBe(QuarterProperty.names().length + 1) + expect(data.length).toBe(propertyNames.length + 1) expect(data[0].length).toBe(3 + 1) expect(data[0]).toEqual(['キー', '項目名', '単位', from]) expect(data[fiscalYearIndex + 1]).toEqual([ @@ -65,7 +63,7 @@ describe('generateData', () => { const data = CsvExporter.generateData(ticker, from, to, today) - expect(data.length).toBe(QuarterProperty.names().length + 1) + expect(data.length).toBe(propertyNames.length + 1) expect(data[0].length).toBe(3 + 1) expect(data[0]).toEqual(['キー', '項目名', '単位', from]) expect(data[fiscalYearIndex + 1]).toEqual([ diff --git a/src/services/csv-exporter.ts b/src/services/csv-exporter.ts index ec5b252..9b6d13d 100644 --- a/src/services/csv-exporter.ts +++ b/src/services/csv-exporter.ts @@ -1,7 +1,6 @@ import { CompanyService } from '~/api/company-service' import { OndemandApiPeriodRange } from '~/api/ondemand-api-period-range' -import { CachingBuffettCodeApiClientV2 } from '~/api/v2/caching-client' -import { CachingQuarterProperty } from '~/api/v2/caching-quarter-property' +import { CachingBuffettCodeApiClientV3 } from '~/api/v3/caching-client' import { YearQuarter } from '~/fiscal-periods/year-quarter' import { YearQuarterParam } from '~/fiscal-periods/year-quarter-param' import { YearQuarterRange } from '~/fiscal-periods/year-quarter-range' @@ -23,7 +22,7 @@ export class CsvExporter { const range = new YearQuarterRange(fromYearQuarter, toYearQuarter) const setting = Setting.load() - const client = new CachingBuffettCodeApiClientV2(setting.token) + const client = new CachingBuffettCodeApiClientV3(setting.token) const companyService = new CompanyService(ticker, client, today) if (!companyService.isSupportedTicker()) { throw new Error('<<サポートされていないtickerです>>') @@ -65,8 +64,8 @@ export class CsvExporter { } const sortedQuarters = quarters.slice().sort((a, b) => { - const labelA = `${a['fiscal_year']}Q${a['fiscal_quarter']}` - const labelB = `${b['fiscal_year']}Q${b['fiscal_quarter']}` + const labelA = a.period().toString() + const labelB = b.period().toString() if (labelA > labelB) { return 1 } else if (labelA < labelB) { @@ -76,18 +75,14 @@ export class CsvExporter { } }) - const quarterLabels = sortedQuarters.map( - quarter => `${quarter['fiscal_year']}Q${quarter['fiscal_quarter']}` + const quarter = quarters[0] + const quarterLabels = sortedQuarters.map(quarter => + quarter.period().toString() ) const header = [['キー', '項目名', '単位', ...quarterLabels]] - const values = CachingQuarterProperty.names().map(name => { - const data = sortedQuarters.map(quarter => quarter[name]) - return [ - name, - CachingQuarterProperty.labelOf(name), - CachingQuarterProperty.unitOf(name), - ...data - ] + const values = quarter.propertyNames().map(name => { + const data = sortedQuarters.map(quarter => quarter.data[name]) + return [name, quarter.labelOf(name), quarter.unitOf(name), ...data] }) return [...header, ...values]