Merged PR 254: API実装(パートナーライセンス情報取得API)
## 概要 [Task2213: API実装(パートナーライセンス情報取得API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2213) - パートナーライセンス情報取得APIについて実装を行いました - このPull Request機能としては対象外。気づいたので直した部分 ・accounts.service.mock.ts →整形されていなかったのを修正、不要な参照を削除 ・accounts.service.spec.ts →整形されていなかったのを修正、不要な参照(userInfo)を削除 ・license.entity.ts →テスト実施のため必須項目の定義を追加 ・dev-database-rg.json →developからのマージだが、差分ファイルとして出てしまっている。 (誤ってコミットのstagingを解除してしまい、後からpull操作したことが影響していると思われる) - 影響範囲(他の機能にも影響があるか) →特になし ## レビューポイント - MISOチームメンバについては、「このPull Request機能としては対象外。気づいたので直した部分」の確認をお願いします。整形や不要な参照はMISOで作りこんだものです。 - accounts.repository.service.tsについて、DRYの観点で一部処理をprivateなサブルーチンとしています(getAccountLicenseOrderStatus)。そもそもそういうことをやってよいか、分ける際のやりかた(引数など)について妥当か見ていただきたいです。 - repositoryからの戻り値型の名称についてわかりやすいかどうか。「PartnerLicenseInfoのうちリポジトリから取得した情報」として「PartnerLicenseInfoFromRepository」としていますが、Fromとかつけない方がよいのでは、とか呼び元を意識しすぎた名称になってる、とか気にしています。 ## UIの変更 - 無し ## 動作確認状況 - ローカルで確認済 ## 補足 - 相談、参考資料などがあれば
This commit is contained in:
parent
63109d9857
commit
70cb66e517
File diff suppressed because it is too large
Load Diff
@ -319,42 +319,10 @@ export class AccountsController {
|
|||||||
@Body() body: GetPartnerLicensesRequest,
|
@Body() body: GetPartnerLicensesRequest,
|
||||||
): Promise<GetPartnerLicensesResponse> {
|
): Promise<GetPartnerLicensesResponse> {
|
||||||
const { limit, offset, accountId } = body;
|
const { limit, offset, accountId } = body;
|
||||||
const accessToken = retrieveAuthorizationToken(req);
|
|
||||||
const payload = jwt.decode(accessToken, { json: true }) as AccessToken;
|
|
||||||
|
|
||||||
// API未実装のうちはサンプルをreturn
|
const getPartnerLicensesResponse =
|
||||||
const ret: GetPartnerLicensesResponse = {
|
await this.accountService.getPartnerLicenses(limit, offset, accountId);
|
||||||
total: 2,
|
|
||||||
ownPartnerLicense: {
|
return getPartnerLicensesResponse;
|
||||||
accountId: 1,
|
|
||||||
tier: 2,
|
|
||||||
companyName: 'testAccount',
|
|
||||||
stockLicense: 30,
|
|
||||||
issuedRequested: 5,
|
|
||||||
shortage: 25,
|
|
||||||
issueRequesting: 100,
|
|
||||||
},
|
|
||||||
childrenPartnerLicenses: [
|
|
||||||
{
|
|
||||||
accountId: 10,
|
|
||||||
tier: 3,
|
|
||||||
companyName: 'testChild',
|
|
||||||
stockLicense: 300,
|
|
||||||
issuedRequested: 50,
|
|
||||||
shortage: 250,
|
|
||||||
issueRequesting: 1000,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accountId: 20,
|
|
||||||
tier: 3,
|
|
||||||
companyName: 'testChild2',
|
|
||||||
stockLicense: 700,
|
|
||||||
issuedRequested: 500,
|
|
||||||
shortage: 200,
|
|
||||||
issueRequesting: 51000,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,14 @@ import {
|
|||||||
makeDefaultUsersRepositoryMockValue,
|
makeDefaultUsersRepositoryMockValue,
|
||||||
} from './test/accounts.service.mock';
|
} from './test/accounts.service.mock';
|
||||||
import { makeDefaultConfigValue } from '../users/test/users.service.mock';
|
import { makeDefaultConfigValue } from '../users/test/users.service.mock';
|
||||||
|
import {
|
||||||
|
createAccount,
|
||||||
|
createLicense,
|
||||||
|
createLicenseOrder,
|
||||||
|
} from './test/utility';
|
||||||
|
import { DataSource } from 'typeorm';
|
||||||
|
import { makeTestingModule } from '../../common/test/modules';
|
||||||
|
import { AccountsService } from './accounts.service';
|
||||||
|
|
||||||
describe('AccountsService', () => {
|
describe('AccountsService', () => {
|
||||||
it('アカウントに紐づくライセンス情報を取得する', async () => {
|
it('アカウントに紐づくライセンス情報を取得する', async () => {
|
||||||
@ -308,20 +316,84 @@ const expectedAccountLisenceCounts = {
|
|||||||
isStorageAvailable: false,
|
isStorageAvailable: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const userInfo = {
|
describe('createPartnerAccount', () => {
|
||||||
accepted_terms_version: '1.0',
|
let source: DataSource = null;
|
||||||
account_id: 1234567890123456,
|
beforeEach(async () => {
|
||||||
author_id: '6cce347f-0cf1-a15e-19ab-d00988b643f9',
|
source = new DataSource({
|
||||||
auto_renew: false,
|
type: 'sqlite',
|
||||||
created_at: new Date('2023-06-13 00:00:00'),
|
database: ':memory:',
|
||||||
created_by: 'test',
|
logging: false,
|
||||||
deleted_at: null,
|
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
|
||||||
email_verified: true,
|
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
|
||||||
external_id: 'ede66c43-9b9d-4222-93ed-5f11c96e08e2',
|
});
|
||||||
id: 1,
|
return source.initialize();
|
||||||
license_alert: false,
|
});
|
||||||
notification: false,
|
|
||||||
role: 'none admin',
|
afterEach(async () => {
|
||||||
updated_at: null,
|
await source.destroy();
|
||||||
updated_by: null,
|
source = null;
|
||||||
};
|
});
|
||||||
|
|
||||||
|
it('パラメータのアカウント自身と子アカウントに紐つくライセンス情報を取得する', async () => {
|
||||||
|
const module = await makeTestingModule(source);
|
||||||
|
|
||||||
|
// 親アカウントと子アカウント2つ作成
|
||||||
|
const { accountId: parentAccountId } = await createAccount(
|
||||||
|
source,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
'PARENTCORP',
|
||||||
|
);
|
||||||
|
const { accountId: childAccountId1 } = await createAccount(
|
||||||
|
source,
|
||||||
|
parentAccountId,
|
||||||
|
2,
|
||||||
|
'CHILDCORP1',
|
||||||
|
);
|
||||||
|
const { accountId: childAccountId2 } = await createAccount(
|
||||||
|
source,
|
||||||
|
parentAccountId,
|
||||||
|
2,
|
||||||
|
'CHILDCORP2',
|
||||||
|
);
|
||||||
|
|
||||||
|
// 所有ライセンスを追加(親:3、子1:1、子2:2)
|
||||||
|
await createLicense(source, parentAccountId);
|
||||||
|
await createLicense(source, parentAccountId);
|
||||||
|
await createLicense(source, parentAccountId);
|
||||||
|
|
||||||
|
await createLicense(source, childAccountId1);
|
||||||
|
|
||||||
|
await createLicense(source, childAccountId2);
|
||||||
|
await createLicense(source, childAccountId2);
|
||||||
|
|
||||||
|
// ライセンス注文を追加(子1→親:10ライセンス、子2→親:5ライセンス)
|
||||||
|
await createLicenseOrder(source, childAccountId1, parentAccountId, 10);
|
||||||
|
await createLicenseOrder(source, childAccountId2, parentAccountId, 5);
|
||||||
|
|
||||||
|
const service = module.get<AccountsService>(AccountsService);
|
||||||
|
const accountId = parentAccountId;
|
||||||
|
const offset = 0;
|
||||||
|
const limit = 20;
|
||||||
|
|
||||||
|
const responce = await service.getPartnerLicenses(limit, offset, accountId);
|
||||||
|
|
||||||
|
expect(responce.total).toBe(2);
|
||||||
|
|
||||||
|
expect(responce.ownPartnerLicense.companyName).toBe('PARENTCORP');
|
||||||
|
expect(responce.ownPartnerLicense.tier).toBe(1);
|
||||||
|
expect(responce.ownPartnerLicense.stockLicense).toBe(3);
|
||||||
|
expect(responce.ownPartnerLicense.issuedRequested).toBe(15);
|
||||||
|
expect(responce.ownPartnerLicense.shortage).toBe(12);
|
||||||
|
|
||||||
|
expect(responce.childrenPartnerLicenses[0].companyName).toBe('CHILDCORP1');
|
||||||
|
expect(responce.childrenPartnerLicenses[0].tier).toBe(2);
|
||||||
|
expect(responce.childrenPartnerLicenses[0].stockLicense).toBe(1);
|
||||||
|
expect(responce.childrenPartnerLicenses[0].issueRequesting).toBe(10);
|
||||||
|
|
||||||
|
expect(responce.childrenPartnerLicenses[1].companyName).toBe('CHILDCORP2');
|
||||||
|
expect(responce.childrenPartnerLicenses[1].tier).toBe(2);
|
||||||
|
expect(responce.childrenPartnerLicenses[1].stockLicense).toBe(2);
|
||||||
|
expect(responce.childrenPartnerLicenses[1].issueRequesting).toBe(5);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@ -16,7 +16,12 @@ import {
|
|||||||
USER_ROLES,
|
USER_ROLES,
|
||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||||||
import { TypistGroup } from './types/types';
|
import {
|
||||||
|
TypistGroup,
|
||||||
|
GetPartnerLicensesResponse,
|
||||||
|
PartnerLicenseInfo,
|
||||||
|
} from './types/types';
|
||||||
|
import { DateWithZeroTime } from '../licenses/types/types';
|
||||||
import { GetLicenseSummaryResponse, Typist } from './types/types';
|
import { GetLicenseSummaryResponse, Typist } from './types/types';
|
||||||
import { AccessToken } from '../../common/token';
|
import { AccessToken } from '../../common/token';
|
||||||
import { UserNotFoundError } from '../../repositories/users/errors/types';
|
import { UserNotFoundError } from '../../repositories/users/errors/types';
|
||||||
@ -45,9 +50,7 @@ export class AccountsService {
|
|||||||
this.logger.log(`[IN] ${this.getLicenseSummary.name}`);
|
this.logger.log(`[IN] ${this.getLicenseSummary.name}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const currentDate = new Date();
|
const currentDate = new DateWithZeroTime();
|
||||||
// 有効期限との比較は時間まで見ず日付だけで判別するため、各値0をセット
|
|
||||||
currentDate.setHours(0, 0, 0, 0);
|
|
||||||
|
|
||||||
const expiringSoonDate = new Date(currentDate.getTime());
|
const expiringSoonDate = new Date(currentDate.getTime());
|
||||||
expiringSoonDate.setDate(
|
expiringSoonDate.setDate(
|
||||||
@ -390,4 +393,83 @@ export class AccountsService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* パートナーライセンス情報を取得する
|
||||||
|
* @param limit
|
||||||
|
* @param offset
|
||||||
|
* @param accountId
|
||||||
|
* @returns getPartnerLicensesResponse
|
||||||
|
*/
|
||||||
|
async getPartnerLicenses(
|
||||||
|
limit: number,
|
||||||
|
offset: number,
|
||||||
|
accountId: number,
|
||||||
|
): Promise<GetPartnerLicensesResponse> {
|
||||||
|
this.logger.log(`[IN] ${this.getPartnerLicenses.name}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const currentDate = new DateWithZeroTime();
|
||||||
|
|
||||||
|
const getPartnerLicenseResult =
|
||||||
|
await this.accountRepository.getPartnerLicense(
|
||||||
|
accountId,
|
||||||
|
currentDate,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 自アカウントのShortageを算出してreturn用の変数にマージする
|
||||||
|
let ownShortage =
|
||||||
|
getPartnerLicenseResult.ownPartnerLicenseFromRepository.stockLicense -
|
||||||
|
getPartnerLicenseResult.ownPartnerLicenseFromRepository.issuedRequested;
|
||||||
|
// 「不足している値」を取得するため、負数の場合は絶対値とし、0以上の場合は0とする
|
||||||
|
ownShortage = ownShortage >= 0 ? 0 : Math.abs(ownShortage);
|
||||||
|
|
||||||
|
// return用の型にリポジトリから取得した型をマージし、不足項目(shortage)を設定する
|
||||||
|
const ownPartnerLicense: PartnerLicenseInfo = Object.assign(
|
||||||
|
{},
|
||||||
|
getPartnerLicenseResult.ownPartnerLicenseFromRepository,
|
||||||
|
{
|
||||||
|
shortage: ownShortage,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 各子アカウントのShortageを算出してreturn用の変数にマージする
|
||||||
|
const childrenPartnerLicenses: PartnerLicenseInfo[] = [];
|
||||||
|
for (const childPartnerLicenseFromRepository of getPartnerLicenseResult.childPartnerLicensesFromRepository) {
|
||||||
|
let childShortage =
|
||||||
|
childPartnerLicenseFromRepository.stockLicense -
|
||||||
|
childPartnerLicenseFromRepository.issuedRequested;
|
||||||
|
// 「不足している値」を取得するため、負数の場合は絶対値とし、0以上の場合は0とする
|
||||||
|
childShortage = childShortage >= 0 ? 0 : Math.abs(childShortage);
|
||||||
|
|
||||||
|
const childPartnerLicense: PartnerLicenseInfo = Object.assign(
|
||||||
|
{},
|
||||||
|
childPartnerLicenseFromRepository,
|
||||||
|
{
|
||||||
|
shortage: childShortage,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
childrenPartnerLicenses.push(childPartnerLicense);
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPartnerLicensesResponse: GetPartnerLicensesResponse = {
|
||||||
|
total: getPartnerLicenseResult.total,
|
||||||
|
ownPartnerLicense: ownPartnerLicense,
|
||||||
|
childrenPartnerLicenses: childrenPartnerLicenses,
|
||||||
|
};
|
||||||
|
|
||||||
|
return getPartnerLicensesResponse;
|
||||||
|
} catch (e) {
|
||||||
|
this.logger.error(e);
|
||||||
|
throw new HttpException(
|
||||||
|
makeErrorResponse('E009999'),
|
||||||
|
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
this.logger.log(`[OUT] ${this.getPartnerLicenses.name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import { Account, LicenseSummaryInfo } from '../types/types';
|
|||||||
import { UserGroup } from '../../../repositories/user_groups/entity/user_group.entity';
|
import { UserGroup } from '../../../repositories/user_groups/entity/user_group.entity';
|
||||||
import { UserGroupsRepositoryService } from '../../../repositories/user_groups/user_groups.repository.service';
|
import { UserGroupsRepositoryService } from '../../../repositories/user_groups/user_groups.repository.service';
|
||||||
import { AdB2cUser } from '../../../gateways/adb2c/types/types';
|
import { AdB2cUser } from '../../../gateways/adb2c/types/types';
|
||||||
import { AccountSASPermissions } from '@azure/storage-blob';
|
|
||||||
export type UsersRepositoryMockValue = {
|
export type UsersRepositoryMockValue = {
|
||||||
findUserById: User | Error;
|
findUserById: User | Error;
|
||||||
findUserByExternalId: User | Error;
|
findUserByExternalId: User | Error;
|
||||||
|
|||||||
74
dictation_server/src/features/accounts/test/utility.ts
Normal file
74
dictation_server/src/features/accounts/test/utility.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { DataSource } from 'typeorm';
|
||||||
|
import { Account } from '../../../repositories/accounts/entity/account.entity';
|
||||||
|
import {
|
||||||
|
License,
|
||||||
|
LicenseOrder,
|
||||||
|
} from '../../../repositories/licenses/entity/license.entity';
|
||||||
|
|
||||||
|
export const createAccount = async (
|
||||||
|
datasource: DataSource,
|
||||||
|
parentAccountId: number,
|
||||||
|
tier: number,
|
||||||
|
companyName: string,
|
||||||
|
): Promise<{ accountId: number }> => {
|
||||||
|
const { identifiers } = await datasource.getRepository(Account).insert({
|
||||||
|
parent_account_id: parentAccountId,
|
||||||
|
tier: tier,
|
||||||
|
country: 'JP',
|
||||||
|
delegation_permission: false,
|
||||||
|
locked: false,
|
||||||
|
company_name: companyName,
|
||||||
|
verified: true,
|
||||||
|
deleted_at: '',
|
||||||
|
created_by: 'test_runner',
|
||||||
|
created_at: new Date(),
|
||||||
|
updated_by: 'updater',
|
||||||
|
updated_at: new Date(),
|
||||||
|
});
|
||||||
|
const account = identifiers.pop() as Account;
|
||||||
|
return { accountId: account.id };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createLicense = async (
|
||||||
|
datasource: DataSource,
|
||||||
|
accountId: number,
|
||||||
|
): Promise<void> => {
|
||||||
|
const { identifiers } = await datasource.getRepository(License).insert({
|
||||||
|
expiry_date: null,
|
||||||
|
account_id: accountId,
|
||||||
|
type: 'NORMAL',
|
||||||
|
status: 'Unallocated',
|
||||||
|
allocated_user_id: null,
|
||||||
|
order_id: null,
|
||||||
|
deleted_at: null,
|
||||||
|
delete_order_id: null,
|
||||||
|
created_by: 'test_runner',
|
||||||
|
created_at: new Date(),
|
||||||
|
updated_by: 'updater',
|
||||||
|
updated_at: new Date(),
|
||||||
|
});
|
||||||
|
identifiers.pop() as License;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createLicenseOrder = async (
|
||||||
|
datasource: DataSource,
|
||||||
|
fromAccountId: number,
|
||||||
|
toAccountId: number,
|
||||||
|
quantity: number,
|
||||||
|
): Promise<void> => {
|
||||||
|
const { identifiers } = await datasource.getRepository(LicenseOrder).insert({
|
||||||
|
po_number: 'TEST123',
|
||||||
|
from_account_id: fromAccountId,
|
||||||
|
to_account_id: toAccountId,
|
||||||
|
ordered_at: new Date(),
|
||||||
|
issued_at: null,
|
||||||
|
quantity: quantity,
|
||||||
|
status: 'Issue Requesting',
|
||||||
|
canceled_at: null,
|
||||||
|
created_by: 'test_runner',
|
||||||
|
created_at: new Date(),
|
||||||
|
updated_by: 'updater',
|
||||||
|
updated_at: new Date(),
|
||||||
|
});
|
||||||
|
identifiers.pop() as License;
|
||||||
|
};
|
||||||
@ -186,3 +186,9 @@ export class GetPartnerLicensesResponse {
|
|||||||
@ApiProperty({ type: [PartnerLicenseInfo] })
|
@ApiProperty({ type: [PartnerLicenseInfo] })
|
||||||
childrenPartnerLicenses: PartnerLicenseInfo[];
|
childrenPartnerLicenses: PartnerLicenseInfo[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RepositoryからPartnerLicenseInfoに関する情報を取得する際の型
|
||||||
|
export type PartnerLicenseInfoForRepository = Omit<
|
||||||
|
PartnerLicenseInfo,
|
||||||
|
'shortage'
|
||||||
|
>;
|
||||||
|
|||||||
@ -36,3 +36,15 @@ export class ActivateCardLicensesRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class ActivateCardLicensesResponse {}
|
export class ActivateCardLicensesResponse {}
|
||||||
|
|
||||||
|
// ライセンス算出用に、その日の始まりの時刻(0:00:00.000)の日付を取得する
|
||||||
|
export class DateWithZeroTime extends Date {
|
||||||
|
constructor(...args: any[]) {
|
||||||
|
if (args.length === 0) {
|
||||||
|
super(); // 引数がない場合、現在の日付で初期化
|
||||||
|
} else {
|
||||||
|
super(...(args as [string])); // 引数がある場合、引数をそのままDateクラスのコンストラクタに渡す
|
||||||
|
}
|
||||||
|
this.setHours(0, 0, 0, 0); // 時分秒を"0:00:00.000"に固定
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
MoreThanOrEqual,
|
MoreThanOrEqual,
|
||||||
Not,
|
Not,
|
||||||
UpdateResult,
|
UpdateResult,
|
||||||
|
EntityManager,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { User } from '../users/entity/user.entity';
|
import { User } from '../users/entity/user.entity';
|
||||||
import { Account } from './entity/account.entity';
|
import { Account } from './entity/account.entity';
|
||||||
@ -21,7 +22,10 @@ import {
|
|||||||
LICENSE_ALLOCATED_STATUS,
|
LICENSE_ALLOCATED_STATUS,
|
||||||
LICENSE_STATUS_ISSUE_REQUESTING,
|
LICENSE_STATUS_ISSUE_REQUESTING,
|
||||||
} from '../../constants';
|
} from '../../constants';
|
||||||
import { LicenseSummaryInfo } from '../../features/accounts/types/types';
|
import {
|
||||||
|
LicenseSummaryInfo,
|
||||||
|
PartnerLicenseInfoForRepository,
|
||||||
|
} from '../../features/accounts/types/types';
|
||||||
import { AccountNotFoundError } from './errors/types';
|
import { AccountNotFoundError } from './errors/types';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@ -290,4 +294,171 @@ export class AccountsRepositoryService {
|
|||||||
return { licenseSummary: licenseSummary, isStorageAvailable };
|
return { licenseSummary: licenseSummary, isStorageAvailable };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ※サブルーチンとして、別途トランザクション開始された処理から呼び出されることを想定
|
||||||
|
* アカウントIDをもとに、ライセンスの注文状況を取得する
|
||||||
|
* @param id
|
||||||
|
* @param currentDate
|
||||||
|
* @param entityManager
|
||||||
|
* @returns stockLicense
|
||||||
|
* @returns issuedRequested
|
||||||
|
* @returns issueRequesting
|
||||||
|
*/
|
||||||
|
private async getAccountLicenseOrderStatus(
|
||||||
|
id: number,
|
||||||
|
currentDate: Date,
|
||||||
|
entityManager: EntityManager,
|
||||||
|
): Promise<{
|
||||||
|
stockLicense: number;
|
||||||
|
issuedRequested: number;
|
||||||
|
issueRequesting: number;
|
||||||
|
}> {
|
||||||
|
const license = entityManager.getRepository(License);
|
||||||
|
const licenseOrder = entityManager.getRepository(LicenseOrder);
|
||||||
|
|
||||||
|
// 有効な総ライセンス数を取得する
|
||||||
|
const stockLicense = await license.count({
|
||||||
|
where: [
|
||||||
|
{
|
||||||
|
account_id: id,
|
||||||
|
expiry_date: MoreThanOrEqual(currentDate),
|
||||||
|
status: Not(LICENSE_ALLOCATED_STATUS.DELETED),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
account_id: id,
|
||||||
|
expiry_date: IsNull(),
|
||||||
|
status: Not(LICENSE_ALLOCATED_STATUS.DELETED),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 子アカウントからの、未発行状態あるいは発行キャンセルされた注文の総ライセンス数を取得する
|
||||||
|
const issuedRequestedSqlResult = await licenseOrder
|
||||||
|
.createQueryBuilder('license_orders')
|
||||||
|
.select('SUM(license_orders.quantity)', 'sum')
|
||||||
|
.where('license_orders.to_account_id = :id', { id })
|
||||||
|
.andWhere('license_orders.status = :status', {
|
||||||
|
status: LICENSE_STATUS_ISSUE_REQUESTING,
|
||||||
|
})
|
||||||
|
.getRawOne();
|
||||||
|
const issuedRequested = parseInt(issuedRequestedSqlResult.sum, 10) || 0;
|
||||||
|
|
||||||
|
// 未発行状態あるいは発行キャンセルされた注文の総ライセンス数を取得する
|
||||||
|
const issuedRequestingSqlResult = await licenseOrder
|
||||||
|
.createQueryBuilder('license_orders')
|
||||||
|
.select('SUM(license_orders.quantity)', 'sum')
|
||||||
|
.where('license_orders.from_account_id = :id', { id })
|
||||||
|
.andWhere('license_orders.status = :status', {
|
||||||
|
status: LICENSE_STATUS_ISSUE_REQUESTING,
|
||||||
|
})
|
||||||
|
.getRawOne();
|
||||||
|
const issuedRequesting = parseInt(issuedRequestingSqlResult.sum, 10) || 0;
|
||||||
|
|
||||||
|
return {
|
||||||
|
stockLicense: stockLicense,
|
||||||
|
issuedRequested: issuedRequested,
|
||||||
|
issueRequesting: issuedRequesting,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* アカウントIDをもとに、自分と子アカウントのライセンス情報を取得する
|
||||||
|
* @param id
|
||||||
|
* @param offset
|
||||||
|
* @param limit
|
||||||
|
* @returns total: 総件数
|
||||||
|
* @returns ownPartnerLicenseFromRepository: リポジトリから取得した自アカウントのライセンス情報
|
||||||
|
* @returns childrenPartnerLicensesFromRepository: リポジトリから取得した子アカウントのライセンス情報
|
||||||
|
*/
|
||||||
|
async getPartnerLicense(
|
||||||
|
id: number,
|
||||||
|
currentDate: Date,
|
||||||
|
offset: number,
|
||||||
|
limit: number,
|
||||||
|
): Promise<{
|
||||||
|
total: number;
|
||||||
|
ownPartnerLicenseFromRepository: PartnerLicenseInfoForRepository;
|
||||||
|
childPartnerLicensesFromRepository: PartnerLicenseInfoForRepository[];
|
||||||
|
}> {
|
||||||
|
return await this.dataSource.transaction(async (entityManager) => {
|
||||||
|
const account = entityManager.getRepository(Account);
|
||||||
|
|
||||||
|
// 自アカウントの情報を取得する
|
||||||
|
const ownAccount = await account.findOne({
|
||||||
|
where: {
|
||||||
|
id: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 自アカウントのライセンス注文状況を取得する
|
||||||
|
const ownLicenseOrderStatus = await this.getAccountLicenseOrderStatus(
|
||||||
|
id,
|
||||||
|
currentDate,
|
||||||
|
entityManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 自アカウントの戻り値を設定する
|
||||||
|
const ownPartnerLicenseFromRepository: PartnerLicenseInfoForRepository = {
|
||||||
|
accountId: id,
|
||||||
|
tier: ownAccount.tier,
|
||||||
|
companyName: ownAccount.company_name,
|
||||||
|
stockLicense: ownLicenseOrderStatus.stockLicense,
|
||||||
|
issuedRequested: ownLicenseOrderStatus.issuedRequested,
|
||||||
|
issueRequesting: ownLicenseOrderStatus.issueRequesting,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 子アカウントのアカウント情報を取得する
|
||||||
|
const childAccounts = await account.find({
|
||||||
|
where: {
|
||||||
|
parent_account_id: id,
|
||||||
|
},
|
||||||
|
order: {
|
||||||
|
company_name: 'ASC',
|
||||||
|
},
|
||||||
|
take: limit,
|
||||||
|
skip: offset,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 各子アカウントのライセンス注文状況を取得する
|
||||||
|
const childPartnerLicensesFromRepository: PartnerLicenseInfoForRepository[] =
|
||||||
|
[];
|
||||||
|
for (const childAccount of childAccounts) {
|
||||||
|
// ライセンス注文状況を取得する
|
||||||
|
const childLicenseOrderStatus = await this.getAccountLicenseOrderStatus(
|
||||||
|
childAccount.id,
|
||||||
|
currentDate,
|
||||||
|
entityManager,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 戻り値用の値を設定
|
||||||
|
const childPartnerLicenseFromRepository: PartnerLicenseInfoForRepository =
|
||||||
|
{
|
||||||
|
accountId: childAccount.id,
|
||||||
|
tier: childAccount.tier,
|
||||||
|
companyName: childAccount.company_name,
|
||||||
|
stockLicense: childLicenseOrderStatus.stockLicense,
|
||||||
|
issuedRequested: childLicenseOrderStatus.issuedRequested,
|
||||||
|
issueRequesting: childLicenseOrderStatus.issueRequesting,
|
||||||
|
};
|
||||||
|
|
||||||
|
childPartnerLicensesFromRepository.push(
|
||||||
|
childPartnerLicenseFromRepository,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// limit/offsetによらない総件数を取得する
|
||||||
|
const total = await account.count({
|
||||||
|
where: {
|
||||||
|
parent_account_id: id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: total,
|
||||||
|
ownPartnerLicenseFromRepository: ownPartnerLicenseFromRepository,
|
||||||
|
childPartnerLicensesFromRepository: childPartnerLicensesFromRepository,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,18 @@ export class LicenseOrder {
|
|||||||
|
|
||||||
@Column({ nullable: true })
|
@Column({ nullable: true })
|
||||||
canceled_at?: Date;
|
canceled_at?: Date;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
created_by: string;
|
||||||
|
|
||||||
|
@CreateDateColumn()
|
||||||
|
created_at: Date;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
updated_by: string;
|
||||||
|
|
||||||
|
@UpdateDateColumn()
|
||||||
|
updated_at: Date;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity({ name: 'licenses' })
|
@Entity({ name: 'licenses' })
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user