diff --git a/dictation_server/src/features/accounts/types/types.ts b/dictation_server/src/features/accounts/types/types.ts index c587255..64dff22 100644 --- a/dictation_server/src/features/accounts/types/types.ts +++ b/dictation_server/src/features/accounts/types/types.ts @@ -24,51 +24,336 @@ import { OPTION_ITEM_VALUE_TYPE } from '../../../constants'; export class CreateAccountRequest { @ApiProperty() + @MaxLength(255) + companyName: string; + + @ApiProperty({ + description: '国名(ISO 3166-1 alpha-2)', + minLength: 2, + maxLength: 2, + }) + @MinLength(2) + @MaxLength(2) + country: string; + + @ApiProperty({ required: false }) + @Type(() => Number) + @IsInt() + @IsOptional() + dealerAccountId?: number; + + @ApiProperty() + @MaxLength(256) // AzureAdB2Cの仕様上、256文字まで[https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/user-profile-attributes] + adminName: string; + + @ApiProperty() + @IsEmail({ blacklisted_chars: '*' }) + adminMail: string; + + @ApiProperty() + @IsAdminPasswordvalid() + adminPassword: string; + + @ApiProperty({ description: '同意済み利用規約のバージョン(EULA)' }) + @MaxLength(255) + acceptedEulaVersion: string; + + @ApiProperty({ description: '同意済みプライバシーポリシーのバージョン' }) + @MaxLength(255) + acceptedPrivacyNoticeVersion: string; + + @ApiProperty({ description: '同意済み利用規約のバージョン(DPA)' }) + @MaxLength(255) + acceptedDpaVersion: string; + + @ApiProperty({ description: 'reCAPTCHA Token' }) + token: string; +} + +export class GetLicenseSummaryRequest { + @ApiProperty() + @Type(() => Number) + @IsInt() + @Min(1) + accountId: number; +} + +export class GetTypistGroupRequest { + @ApiProperty() + @Type(() => Number) + @IsInt() + @Min(1) + typistGroupId: number; +} + +export class CreateTypistGroupRequest { + @ApiProperty({ minLength: 1, maxLength: 50 }) + @MinLength(1) + @MaxLength(50) + typistGroupName: string; + @ApiProperty({ minItems: 1, isArray: true, type: 'integer' }) + @ArrayMinSize(1) + @IsArray() + @IsInt({ each: true }) + @Min(1, { each: true }) + @IsUnique() + typistIds: number[]; +} + +export class UpdateTypistGroupRequest { + @ApiProperty({ minLength: 1, maxLength: 50 }) + @MinLength(1) + @MaxLength(50) + typistGroupName: string; + @ApiProperty({ minItems: 1, isArray: true, type: 'integer' }) + @ArrayMinSize(1) + @IsArray() + @IsInt({ each: true }) + @Min(1, { each: true }) + @IsUnique() + typistIds: number[]; +} +export class UpdateTypistGroupRequestParam { + @ApiProperty() + @Type(() => Number) + @IsInt() + @Min(1) + typistGroupId: number; +} +export class CreatePartnerAccountRequest { + @ApiProperty() + @MaxLength(255) companyName: string; @ApiProperty({ description: '国名(ISO 3166-1 alpha-2)', minLength: 2, maxLength: 2, }) + @MinLength(2) + @MaxLength(2) country: string; - @ApiProperty({ required: false }) - @IsInt() - @IsOptional() - dealerAccountId?: number; @ApiProperty() + @MaxLength(256) // AzureAdB2Cの仕様上、256文字まで[https://learn.microsoft.com/ja-jp/azure/active-directory-b2c/user-profile-attributes] adminName: string; @ApiProperty() @IsEmail({ blacklisted_chars: '*' }) - adminMail: string; - @ApiProperty() - @IsAdminPasswordvalid() - adminPassword: string; - @ApiProperty({ description: '同意済み利用規約のバージョン(EULA)' }) - acceptedEulaVersion: string; - @ApiProperty({ description: '同意済みプライバシーポリシーのバージョン' }) - acceptedPrivacyNoticeVersion: string; - @ApiProperty({ description: '同意済み利用規約のバージョン(DPA)' }) - acceptedDpaVersion: string; - @ApiProperty({ description: 'reCAPTCHA Token' }) - token: string; + email: string; } +export class GetPartnerLicensesRequest { + @ApiProperty() + @IsInt() + @Type(() => Number) + @Min(0) + limit: number; + @ApiProperty() + @IsInt() + @Type(() => Number) + @Min(0) + offset: number; + @ApiProperty() + @IsInt() + @Type(() => Number) + accountId: number; +} + +export class GetOrderHistoriesRequest { + @ApiProperty({ description: '取得件数' }) + @IsInt() + @Min(0) + @Type(() => Number) + limit: number; + @ApiProperty({ description: '開始位置' }) + @IsInt() + @Min(0) + @Type(() => Number) + offset: number; + @ApiProperty({ description: 'アカウントID' }) + @IsInt() + @Type(() => Number) + accountId: number; +} + +export class IssueLicenseRequest { + @ApiProperty({ description: '注文元アカウントID' }) + @IsInt() + @Type(() => Number) + orderedAccountId: number; + @ApiProperty({ description: 'POナンバー' }) + @Matches(/^[A-Z0-9]+$/) + poNumber: string; +} + +export class CancelIssueRequest { + @ApiProperty({ description: '注文元アカウントID' }) + @IsInt() + @Type(() => Number) + orderedAccountId: number; + + @ApiProperty({ description: 'POナンバー' }) + @Matches(/^[A-Z0-9]+$/) + poNumber: string; +} + +export class CreateWorktypesRequest { + @ApiProperty({ minLength: 1, maxLength: 255, description: 'WorktypeID' }) + @MinLength(1) + @MaxLength(255) + @IsRecorderAllowed() + worktypeId: string; + @ApiProperty({ description: 'Worktypeの説明', required: false }) + @MaxLength(255) + @IsOptional() + description?: string; +} + +export class UpdateWorktypesRequest { + @ApiProperty({ minLength: 1, description: 'WorktypeID' }) + @MinLength(1) + @MaxLength(255) + @IsRecorderAllowed() + worktypeId: string; + @ApiProperty({ description: 'Worktypeの説明', required: false }) + @MaxLength(255) + @IsOptional() + description?: string; +} + +export class PostWorktypeOptionItem { + @ApiProperty({ maxLength: 16 }) + @MaxLength(16) + @IsRecorderAllowed() + itemLabel: string; + @ApiProperty({ + maxLength: 20, + description: `${Object.values(OPTION_ITEM_VALUE_TYPE).join(' / ')}`, + }) + @MaxLength(20) + @IsIn(Object.values(OPTION_ITEM_VALUE_TYPE)) + defaultValueType: string; + @ApiProperty({ maxLength: 20 }) + @MaxLength(20) + @IsRecorderAllowed() + @IsInitialValue() + initialValue: string; +} + +export class GetOptionItemsRequestParam { + @ApiProperty({ description: 'Worktypeの内部ID' }) + @Type(() => Number) + @IsInt() + @Min(1) + id: number; +} + +export class UpdateOptionItemsRequest { + @ApiProperty({ + maxItems: 10, + minItems: 10, + type: [PostWorktypeOptionItem], + }) + @IsArray() + @ValidateNested({ each: true }) + @Type(() => PostWorktypeOptionItem) + @ArrayMinSize(10) + @ArrayMaxSize(10) + optionItems: PostWorktypeOptionItem[]; +} + +export class UpdateOptionItemsRequestParam { + @ApiProperty({ description: 'Worktypeの内部ID' }) + @Type(() => Number) + @IsInt() + @Min(1) + id: number; +} + +export class UpdateWorktypeRequestParam { + @ApiProperty({ description: 'Worktypeの内部ID' }) + @Type(() => Number) + @IsInt() + @Min(1) + id: number; +} + +export class DeleteWorktypeRequestParam { + @ApiProperty({ description: 'Worktypeの内部ID' }) + @Type(() => Number) + @IsInt() + @Min(1) + id: number; +} + +export class PostActiveWorktypeRequest { + @ApiProperty({ + required: false, + description: 'Active WorkTypeIDにするWorktypeの内部ID', + }) + @IsOptional() + @Type(() => Number) + @IsInt() + @Min(1) + id?: number; +} + +export class GetPartnersRequest { + @ApiProperty({ description: '取得件数' }) + @IsInt() + @Min(0) + @Type(() => Number) + limit: number; + @ApiProperty({ description: '開始位置' }) + @IsInt() + @Min(0) + @Type(() => Number) + offset: number; +} + +export class UpdateAccountInfoRequest { + @ApiProperty({ description: '親アカウントのID', required: false }) + @Type(() => Number) + @IsInt() + @IsOptional() + parentAccountId?: number; + @ApiProperty({ description: '代行操作許可' }) + @Type(() => Boolean) + delegationPermission: boolean; + @ApiProperty({ description: 'プライマリ管理者ID' }) + @Type(() => Number) + @IsInt() + primaryAdminUserId: number; + @ApiProperty({ description: 'セカンダリ管理者ID', required: false }) + @Type(() => Number) + @IsInt() + @IsOptional() + secondryAdminUserId?: number; +} + +export class DeleteAccountRequest { + @ApiProperty({ description: 'アカウントID' }) + @Type(() => Number) + @IsInt() + accountId: number; +} + +export class GetAccountInfoMinimalAccessRequest { + @ApiProperty({ description: 'idトークン' }) + idToken: string; +} + +export class GetCompanyNameRequest { + @ApiProperty() + @IsInt() + @Type(() => Number) + accountId: number; +} + +// ============================== +// RESPONSE +// ============================== + export class CreateAccountResponse {} -export class GetLicenseSummaryRequest { - @ApiProperty() - accountId: number; -} -export class LicenseSummaryInfo { - totalLicense: number; - allocatedLicense: number; - reusableLicense: number; - freeLicense: number; - expiringSoonLicense: number; - issueRequesting: number; - numberOfRequesting: number; - allocatableLicenseWithMargin: number; -} export class GetLicenseSummaryResponse { @ApiProperty() totalLicense: number; @@ -104,6 +389,11 @@ export class GetLicenseSummaryResponse { isStorageAvailable: boolean; } +export class GetCompanyNameResponse { + @ApiProperty() + companyName: string; +} + export class Account { @ApiProperty() accountId: number; @@ -133,11 +423,6 @@ export class Account { parentAccountName?: string; } -export class GetMyAccountResponse { - @ApiProperty({ type: Account }) - account: Account; -} - export class Author { @ApiProperty({ description: 'Authorユーザーの内部ID' }) id: number; @@ -145,11 +430,6 @@ export class Author { authorId: string; } -export class GetAuthorsResponse { - @ApiProperty({ type: [Author] }) - authors: Author[]; -} - export class Typist { @ApiProperty({ description: 'TypistのユーザーID', @@ -160,11 +440,6 @@ export class Typist { name: string; } -export class GetTypistsResponse { - @ApiProperty({ type: [Typist] }) - typists: Typist[]; -} - export class TypistGroup { @ApiProperty({ description: 'TypistGroupのID', @@ -175,18 +450,26 @@ export class TypistGroup { name: string; } +export class GetMyAccountResponse { + @ApiProperty({ type: Account }) + account: Account; +} + +export class GetAuthorsResponse { + @ApiProperty({ type: [Author] }) + authors: Author[]; +} + +export class GetTypistsResponse { + @ApiProperty({ type: [Typist] }) + typists: Typist[]; +} + export class GetTypistGroupsResponse { @ApiProperty({ type: [TypistGroup] }) typistGroups: TypistGroup[]; } -export class GetTypistGroupRequest { - @ApiProperty() - @Type(() => Number) - @IsInt() - @Min(1) - typistGroupId: number; -} export class GetTypistGroupResponse { @ApiProperty() typistGroupName: string; @@ -194,72 +477,12 @@ export class GetTypistGroupResponse { typistIds: number[]; } -export class CreateTypistGroupRequest { - @ApiProperty({ minLength: 1, maxLength: 50 }) - @MinLength(1) - @MaxLength(50) - typistGroupName: string; - @ApiProperty({ minItems: 1, isArray: true, type: 'integer' }) - @ArrayMinSize(1) - @IsArray() - @IsInt({ each: true }) - @Min(1, { each: true }) - @IsUnique() - typistIds: number[]; -} - export class CreateTypistGroupResponse {} -export class UpdateTypistGroupRequest { - @ApiProperty({ minLength: 1, maxLength: 50 }) - @MinLength(1) - @MaxLength(50) - typistGroupName: string; - @ApiProperty({ minItems: 1, isArray: true, type: 'integer' }) - @ArrayMinSize(1) - @IsArray() - @IsInt({ each: true }) - @Min(1, { each: true }) - @IsUnique() - typistIds: number[]; -} -export class UpdateTypistGroupRequestParam { - @ApiProperty() - @Type(() => Number) - @IsInt() - @Min(1) - typistGroupId: number; -} export class UpdateTypistGroupResponse {} -export class CreatePartnerAccountRequest { - @ApiProperty() - companyName: string; - @ApiProperty({ - description: '国名(ISO 3166-1 alpha-2)', - minLength: 2, - maxLength: 2, - }) - country: string; - @ApiProperty() - adminName: string; - @ApiProperty() - @IsEmail({ blacklisted_chars: '*' }) - email: string; -} - export class CreatePartnerAccountResponse {} -export class GetPartnerLicensesRequest { - @ApiProperty() - @IsInt() - limit: number; - @ApiProperty() - @IsInt() - offset: number; - @ApiProperty() - accountId: number; -} export class PartnerLicenseInfo { @ApiProperty({ description: 'アカウントID' }) @@ -291,7 +514,6 @@ export class PartnerLicenseInfo { }) issueRequesting: number; } - export class GetPartnerLicensesResponse { @ApiProperty() total: number; @@ -301,30 +523,6 @@ export class GetPartnerLicensesResponse { childrenPartnerLicenses: PartnerLicenseInfo[]; } -// 第五階層のshortage算出用 -export class PartnerLicenseInfoForShortage { - expiringSoonLicense?: number; - allocatableLicenseWithMargin?: number; -} - -// RepositoryからPartnerLicenseInfoに関する情報を取得する際の型 -export type PartnerLicenseInfoForRepository = Omit< - PartnerLicenseInfo & PartnerLicenseInfoForShortage, - 'shortage' ->; - -export class GetOrderHistoriesRequest { - @ApiProperty({ description: '取得件数' }) - @IsInt() - @Min(0) - limit: number; - @ApiProperty({ description: '開始位置' }) - @IsInt() - @Min(0) - offset: number; - @ApiProperty({ description: 'アカウントID' }) - accountId: number; -} export class LicenseOrder { @ApiProperty({ description: '注文日付' }) @@ -338,6 +536,7 @@ export class LicenseOrder { @ApiProperty({ description: '注文状態' }) status: string; } + export class GetOrderHistoriesResponse { @ApiProperty({ description: '合計件数' }) total: number; @@ -345,16 +544,9 @@ export class GetOrderHistoriesResponse { orderHistories: LicenseOrder[]; } -export class IssueLicenseRequest { - @ApiProperty({ description: '注文元アカウントID' }) - orderedAccountId: number; - @ApiProperty({ description: 'POナンバー' }) - @Matches(/^[A-Z0-9]+$/) - poNumber: string; -} - export class IssueLicenseResponse {} + export class Dealer { @ApiProperty({ description: 'アカウントID' }) id: number; @@ -363,22 +555,15 @@ export class Dealer { @ApiProperty({ description: '国名(ISO 3166-1 alpha-2)' }) country: string; } + export class GetDealersResponse { @ApiProperty({ type: [Dealer] }) dealers: Dealer[]; } -export class CancelIssueRequest { - @ApiProperty({ description: '注文元アカウントID' }) - orderedAccountId: number; - - @ApiProperty({ description: 'POナンバー' }) - @Matches(/^[A-Z0-9]+$/) - poNumber: string; -} - export class CancelIssueResponse {} + export class Worktype { @ApiProperty({ description: 'WorktypeのID' }) id: number; @@ -399,52 +584,11 @@ export class GetWorktypesResponse { active?: number; } -export class CreateWorktypesRequest { - @ApiProperty({ minLength: 1, maxLength: 255, description: 'WorktypeID' }) - @MinLength(1) - @MaxLength(255) - @IsRecorderAllowed() - worktypeId: string; - @ApiProperty({ description: 'Worktypeの説明', required: false }) - @MaxLength(255) - @IsOptional() - description?: string; -} - export class CreateWorktypeResponse {} -export class UpdateWorktypesRequest { - @ApiProperty({ minLength: 1, description: 'WorktypeID' }) - @MinLength(1) - @MaxLength(255) - @IsRecorderAllowed() - worktypeId: string; - @ApiProperty({ description: 'Worktypeの説明', required: false }) - @MaxLength(255) - @IsOptional() - description?: string; -} - export class UpdateWorktypeResponse {} -export class PostWorktypeOptionItem { - @ApiProperty({ maxLength: 16 }) - @MaxLength(16) - @IsRecorderAllowed() - itemLabel: string; - @ApiProperty({ - maxLength: 20, - description: `${Object.values(OPTION_ITEM_VALUE_TYPE).join(' / ')}`, - }) - @MaxLength(20) - @IsIn(Object.values(OPTION_ITEM_VALUE_TYPE)) - defaultValueType: string; - @ApiProperty({ maxLength: 20 }) - @MaxLength(20) - @IsRecorderAllowed() - @IsInitialValue() - initialValue: string; -} + export class GetWorktypeOptionItem extends PostWorktypeOptionItem { @ApiProperty() id: number; @@ -459,82 +603,12 @@ export class GetOptionItemsResponse { optionItems: GetWorktypeOptionItem[]; } -export class GetOptionItemsRequestParam { - @ApiProperty({ description: 'Worktypeの内部ID' }) - @Type(() => Number) - @IsInt() - @Min(1) - id: number; -} - -export class UpdateOptionItemsRequest { - @ApiProperty({ - maxItems: 10, - minItems: 10, - type: [PostWorktypeOptionItem], - }) - @IsArray() - @ValidateNested({ each: true }) - @Type(() => PostWorktypeOptionItem) - @ArrayMinSize(10) - @ArrayMaxSize(10) - optionItems: PostWorktypeOptionItem[]; -} - export class UpdateOptionItemsResponse {} -export class UpdateOptionItemsRequestParam { - @ApiProperty({ description: 'Worktypeの内部ID' }) - @Type(() => Number) - @IsInt() - @Min(1) - id: number; -} - -export class UpdateWorktypeRequestParam { - @ApiProperty({ description: 'Worktypeの内部ID' }) - @Type(() => Number) - @IsInt() - @Min(1) - id: number; -} - -export class DeleteWorktypeRequestParam { - @ApiProperty({ description: 'Worktypeの内部ID' }) - @Type(() => Number) - @IsInt() - @Min(1) - id: number; -} - export class DeleteWorktypeResponse {} -export class PostActiveWorktypeRequest { - @ApiProperty({ - required: false, - description: 'Active WorkTypeIDにするWorktypeの内部ID', - }) - @IsOptional() - @Type(() => Number) - @IsInt() - @Min(1) - id?: number; -} - export class PostActiveWorktypeResponse {} -export class GetPartnersRequest { - @ApiProperty({ description: '取得件数' }) - @IsInt() - @Min(0) - @Type(() => Number) - limit: number; - @ApiProperty({ description: '開始位置' }) - @IsInt() - @Min(0) - @Type(() => Number) - offset: number; -} export class Partner { @ApiProperty({ description: '会社名' }) @@ -560,6 +634,42 @@ export class GetPartnersResponse { partners: Partner[]; } +export class UpdateAccountInfoResponse {} + +export class DeleteAccountResponse {} + +export class GetAccountInfoMinimalAccessResponse { + @ApiProperty({ description: '階層' }) + tier: number; +} + +// ============================== +// Request/Response外の型 +// TODO: Request/Response/その他の型を別ファイルに分ける +// ============================== +export class LicenseSummaryInfo { + totalLicense: number; + allocatedLicense: number; + reusableLicense: number; + freeLicense: number; + expiringSoonLicense: number; + issueRequesting: number; + numberOfRequesting: number; + allocatableLicenseWithMargin: number; +} + +// 第五階層のshortage算出用 +export class PartnerLicenseInfoForShortage { + expiringSoonLicense?: number; + allocatableLicenseWithMargin?: number; +} + +// RepositoryからPartnerLicenseInfoに関する情報を取得する際の型 +export type PartnerLicenseInfoForRepository = Omit< + PartnerLicenseInfo & PartnerLicenseInfoForShortage, + 'shortage' +>; + // RepositoryからPartnerLicenseInfoに関する情報を取得する際の型 export type PartnerInfoFromDb = { name: string; @@ -568,46 +678,4 @@ export type PartnerInfoFromDb = { country: string; primaryAccountExternalId: string; dealerManagement: boolean; -}; - -export class UpdateAccountInfoRequest { - @ApiProperty({ description: '親アカウントのID', required: false }) - @IsOptional() - parentAccountId?: number; - @ApiProperty({ description: '代行操作許可' }) - delegationPermission: boolean; - @ApiProperty({ description: 'プライマリ管理者ID' }) - primaryAdminUserId: number; - @ApiProperty({ description: 'セカンダリ管理者ID', required: false }) - @IsOptional() - secondryAdminUserId?: number; -} - -export class UpdateAccountInfoResponse {} - -export class DeleteAccountRequest { - @ApiProperty({ description: 'アカウントID' }) - accountId: number; -} - -export class DeleteAccountResponse {} - -export class GetAccountInfoMinimalAccessRequest { - @ApiProperty({ description: 'idトークン' }) - idToken: string; -} - -export class GetAccountInfoMinimalAccessResponse { - @ApiProperty({ description: '階層' }) - tier: number; -} -export class GetCompanyNameRequest { - @ApiProperty() - @IsInt() - @Type(() => Number) - accountId: number; -} -export class GetCompanyNameResponse { - @ApiProperty() - companyName: string; -} +}; \ No newline at end of file diff --git a/dictation_server/src/repositories/accounts/accounts.repository.service.ts b/dictation_server/src/repositories/accounts/accounts.repository.service.ts index 745adb6..2d0d78c 100644 --- a/dictation_server/src/repositories/accounts/accounts.repository.service.ts +++ b/dictation_server/src/repositories/accounts/accounts.repository.service.ts @@ -31,11 +31,6 @@ import { LICENSE_ISSUE_STATUS, TIERS, } from '../../constants'; -import { - LicenseSummaryInfo, - PartnerLicenseInfoForRepository, - PartnerInfoFromDb, -} from '../../features/accounts/types/types'; import { AccountNotFoundError, AdminUserNotFoundError, @@ -64,6 +59,7 @@ import { deleteEntity, } from '../../common/repository'; import { Context } from '../../common/log'; +import { LicenseSummaryInfo, PartnerInfoFromDb, PartnerLicenseInfoForRepository } from '../../features/accounts/types/types'; @Injectable() export class AccountsRepositoryService {