diff --git a/dictation_server/src/features/accounts/accounts.service.ts b/dictation_server/src/features/accounts/accounts.service.ts index ed80bb5..bc134ad 100644 --- a/dictation_server/src/features/accounts/accounts.service.ts +++ b/dictation_server/src/features/accounts/accounts.service.ts @@ -435,12 +435,32 @@ export class AccountsService { }, ); + // 第五階層のshortage算出に使用する日付情報 + // 「有効期限が現在日付からしきい値以内のライセンス数」を取得するため、しきい値となる日付を作成する + const expiringSoonDate = new Date(currentDate.getTime()); + expiringSoonDate.setDate( + currentDate.getDate() + LICENSE_EXPIRATION_THRESHOLD_DAYS, + ); + expiringSoonDate.setHours(23, 59, 59, 999); + // 各子アカウントのShortageを算出してreturn用の変数にマージする const childrenPartnerLicenses: PartnerLicenseInfo[] = []; for (const childPartnerLicenseFromRepository of getPartnerLicenseResult.childPartnerLicensesFromRepository) { - let childShortage = - childPartnerLicenseFromRepository.stockLicense - - childPartnerLicenseFromRepository.issuedRequested; + let childShortage; + if (childPartnerLicenseFromRepository.tier === TIERS.TIER5) { + // 第五階層の場合計算式が異なるため、別途値を取得する + const { expiringSoonLicense, allocatableLicenseWithMargin } = + await this.accountRepository.getLicenseCountForShortage( + childPartnerLicenseFromRepository.accountId, + currentDate, + expiringSoonDate, + ); + childShortage = allocatableLicenseWithMargin - expiringSoonLicense; + } else { + childShortage = + childPartnerLicenseFromRepository.stockLicense - + childPartnerLicenseFromRepository.issuedRequested; + } // 「不足している値」を取得するため、負数の場合は絶対値とし、0以上の場合は0とする childShortage = childShortage >= 0 ? 0 : Math.abs(childShortage); diff --git a/dictation_server/src/repositories/accounts/accounts.repository.service.ts b/dictation_server/src/repositories/accounts/accounts.repository.service.ts index 77a66d6..c195fbf 100644 --- a/dictation_server/src/repositories/accounts/accounts.repository.service.ts +++ b/dictation_server/src/repositories/accounts/accounts.repository.service.ts @@ -167,6 +167,75 @@ export class AccountsRepositoryService { return account; } + /** + * ※サブルーチンとして、別途トランザクション開始された処理から呼び出されることを想定 + * 有効期限が現在日付からしきい値以内のライセンス数を取得する + * @param entityManager + * @param id + * @param currentDate + * @param expiringSoonDate + * @returns expiringSoonLicense + */ + private async getExpiringSoonLicense( + entityManager: EntityManager, + id: number, + currentDate: Date, + expiringSoonDate: Date, + ): Promise { + const license = entityManager.getRepository(License); + + // 有効期限が現在日付からしきい値以内のライセンス数を取得する + const expiringSoonLicense = await license.count({ + where: { + account_id: id, + expiry_date: Between(currentDate, expiringSoonDate), + status: Not(LICENSE_ALLOCATED_STATUS.DELETED), + }, + }); + + return expiringSoonLicense; + } + + /** + * ※サブルーチンとして、別途トランザクション開始された処理から呼び出されることを想定 + * 有効期限がしきい値より未来または未設定で、割り当て可能なライセンス数の取得を行う + * @param entityManager + * @param id + * @param expiringSoonDate + * @returns allocatableLicenseWithMargin + */ + private async getAllocatableLicenseWithMargin( + entityManager: EntityManager, + id: number, + expiringSoonDate: Date, + ): Promise { + const license = entityManager.getRepository(License); + + // 有効期限がしきい値より未来または未設定で、割り当て可能なライセンス数の取得を行う + const allocatableLicenseWithMargin = await license.count({ + where: [ + { + account_id: id, + status: In([ + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + LICENSE_ALLOCATED_STATUS.REUSABLE, + ]), + expiry_date: MoreThan(expiringSoonDate), + }, + { + account_id: id, + status: In([ + LICENSE_ALLOCATED_STATUS.UNALLOCATED, + LICENSE_ALLOCATED_STATUS.REUSABLE, + ]), + expiry_date: IsNull(), + }, + ], + }); + + return allocatableLicenseWithMargin; + } + /** * アカウントIDからライセンス情報を取得する * @param id @@ -228,13 +297,12 @@ export class AccountsRepositoryService { }); // 有効期限が現在日付からしきい値以内のライセンス数を取得する - const expiringSoonLicense = await license.count({ - where: { - account_id: id, - expiry_date: Between(currentDate, expiringSoonDate), - status: Not(LICENSE_ALLOCATED_STATUS.DELETED), - }, - }); + const expiringSoonLicense = await this.getExpiringSoonLicense( + entityManager, + id, + currentDate, + expiringSoonDate, + ); // 未発行状態あるいは発行キャンセルされた注文数を取得する const numberOfRequesting = await licenseOrder.count({ @@ -256,26 +324,12 @@ export class AccountsRepositoryService { const issueRequesting = parseInt(result.sum, 10) || 0; // 有効期限がしきい値より未来または未設定で、割り当て可能なライセンス数の取得を行う - const allocatableLicenseWithMargin = await license.count({ - where: [ - { - account_id: id, - status: In([ - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - LICENSE_ALLOCATED_STATUS.REUSABLE, - ]), - expiry_date: MoreThan(expiringSoonDate), - }, - { - account_id: id, - status: In([ - LICENSE_ALLOCATED_STATUS.UNALLOCATED, - LICENSE_ALLOCATED_STATUS.REUSABLE, - ]), - expiry_date: IsNull(), - }, - ], - }); + const allocatableLicenseWithMargin = + await this.getAllocatableLicenseWithMargin( + entityManager, + id, + expiringSoonDate, + ); // アカウントのロック状態を取得する const isStorageAvailable = (await this.findAccountById(id)).locked; @@ -461,4 +515,40 @@ export class AccountsRepositoryService { }; }); } + + /** + * 不足数を算出するためのライセンス数情報を取得する + * @param id + * @param currentDate + * @param expiringSoonDate + * @returns expiringSoonLicense + * @returns expiringSoonDate + */ + async getLicenseCountForShortage( + id: number, + currentDate: Date, + expiringSoonDate: Date, + ): Promise<{ + expiringSoonLicense: number; + allocatableLicenseWithMargin: number; + }> { + return await this.dataSource.transaction(async (entityManager) => { + const expiringSoonLicense = await this.getExpiringSoonLicense( + entityManager, + id, + currentDate, + expiringSoonDate, + ); + const allocatableLicenseWithMargin = + await this.getAllocatableLicenseWithMargin( + entityManager, + id, + expiringSoonDate, + ); + return { + expiringSoonLicense: expiringSoonLicense, + allocatableLicenseWithMargin: allocatableLicenseWithMargin, + }; + }); + } }