Merged PR 333: 動作確認不具合修正

## 概要
[Task2419: 動作確認不具合修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2419)

- ディーラーをURLで指定して見つからなかった場合にスナックバーでメッセージを表示するように修正しました。

## レビューポイント
- UIの挙動として問題ないか
- メッセージは適切か

## UIの変更
- [Task2419](https://ndstokyo.sharepoint.com/:f:/r/sites/Piranha/Shared%20Documents/General/OMDS/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88/Task2419?csf=1&web=1&e=v1C0ki)

## 動作確認状況
- ローカルで確認
This commit is contained in:
makabe.t 2023-08-17 08:08:28 +00:00
parent 073e28d67d
commit adbd57bca6
11 changed files with 251 additions and 25 deletions

View File

@ -68,6 +68,44 @@ export interface ActivateCardLicensesRequest {
*/
'cardLicenseKey': string;
}
/**
*
* @export
* @interface AllocatableLicenseInfo
*/
export interface AllocatableLicenseInfo {
/**
*
* @type {number}
* @memberof AllocatableLicenseInfo
*/
'licenseId': number;
/**
*
* @type {string}
* @memberof AllocatableLicenseInfo
*/
'expiryDate': string;
}
/**
*
* @export
* @interface AllocateLicenseRequest
*/
export interface AllocateLicenseRequest {
/**
* ID
* @type {number}
* @memberof AllocateLicenseRequest
*/
'userId': number;
/**
* ID
* @type {number}
* @memberof AllocateLicenseRequest
*/
'newLicenseId': number;
}
/**
*
* @export
@ -291,7 +329,7 @@ export interface CreateAccountRequest {
* @type {number}
* @memberof CreateAccountRequest
*/
'dealerAccountId': number | null;
'dealerAccountId'?: number;
/**
*
* @type {string}
@ -417,6 +455,19 @@ export interface ErrorResponse {
*/
'code': string;
}
/**
*
* @export
* @interface GetAllocatableLicensesResponse
*/
export interface GetAllocatableLicensesResponse {
/**
*
* @type {Array<AllocatableLicenseInfo>}
* @memberof GetAllocatableLicensesResponse
*/
'allocatableLicenses': Array<AllocatableLicenseInfo>;
}
/**
*
* @export
@ -2862,6 +2913,46 @@ export const LicensesApiAxiosParamCreator = function (configuration?: Configurat
options: localVarRequestOptions,
};
},
/**
*
* @summary
* @param {object} body
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getAllocatableLicenses: async (body: object, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'body' is not null or undefined
assertParamExists('getAllocatableLicenses', 'body', body)
const localVarPath = `/licenses/allocatable`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication bearer required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(body, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary
@ -2934,6 +3025,17 @@ export const LicensesApiFp = function(configuration?: Configuration) {
const localVarAxiosArgs = await localVarAxiosParamCreator.createOrders(createOrdersRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary
* @param {object} body
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getAllocatableLicenses(body: object, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<GetAllocatableLicensesResponse>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getAllocatableLicenses(body, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary
@ -2975,6 +3077,16 @@ export const LicensesApiFactory = function (configuration?: Configuration, baseP
createOrders(createOrdersRequest: CreateOrdersRequest, options?: any): AxiosPromise<object> {
return localVarFp.createOrders(createOrdersRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
* @param {object} body
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getAllocatableLicenses(body: object, options?: any): AxiosPromise<GetAllocatableLicensesResponse> {
return localVarFp.getAllocatableLicenses(body, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
@ -3019,6 +3131,18 @@ export class LicensesApi extends BaseAPI {
return LicensesApiFp(this.configuration).createOrders(createOrdersRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
* @param {object} body
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof LicensesApi
*/
public getAllocatableLicenses(body: object, options?: AxiosRequestConfig) {
return LicensesApiFp(this.configuration).getAllocatableLicenses(body, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary
@ -3872,6 +3996,46 @@ export class TasksApi extends BaseAPI {
*/
export const UsersApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
*
* @summary
* @param {AllocateLicenseRequest} allocateLicenseRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
allocateLicense: async (allocateLicenseRequest: AllocateLicenseRequest, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'allocateLicenseRequest' is not null or undefined
assertParamExists('allocateLicense', 'allocateLicenseRequest', allocateLicenseRequest)
const localVarPath = `/users/license/allocate`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
let baseOptions;
if (configuration) {
baseOptions = configuration.baseOptions;
}
const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options};
const localVarHeaderParameter = {} as any;
const localVarQueryParameter = {} as any;
// authentication bearer required
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(allocateLicenseRequest, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
*
* @summary
@ -4176,6 +4340,17 @@ export const UsersApiAxiosParamCreator = function (configuration?: Configuration
export const UsersApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = UsersApiAxiosParamCreator(configuration)
return {
/**
*
* @summary
* @param {AllocateLicenseRequest} allocateLicenseRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async allocateLicense(allocateLicenseRequest: AllocateLicenseRequest, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<object>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.allocateLicense(allocateLicenseRequest, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
*
* @summary
@ -4271,6 +4446,16 @@ export const UsersApiFp = function(configuration?: Configuration) {
export const UsersApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = UsersApiFp(configuration)
return {
/**
*
* @summary
* @param {AllocateLicenseRequest} allocateLicenseRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
allocateLicense(allocateLicenseRequest: AllocateLicenseRequest, options?: any): AxiosPromise<object> {
return localVarFp.allocateLicense(allocateLicenseRequest, options).then((request) => request(axios, basePath));
},
/**
*
* @summary
@ -4358,6 +4543,18 @@ export const UsersApiFactory = function (configuration?: Configuration, basePath
* @extends {BaseAPI}
*/
export class UsersApi extends BaseAPI {
/**
*
* @summary
* @param {AllocateLicenseRequest} allocateLicenseRequest
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof UsersApi
*/
public allocateLicense(allocateLicenseRequest: AllocateLicenseRequest, options?: AxiosRequestConfig) {
return UsersApiFp(this.configuration).allocateLicense(allocateLicenseRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
*
* @summary

View File

@ -33,7 +33,7 @@ const SignupConfirm: React.FC = (): JSX.Element => {
signupAsync({
companyName,
country,
dealerAccountId: dealer?.id ?? 0,
dealerAccountId: dealer?.id ?? undefined,
adminName,
adminMail,
adminPassword,

View File

@ -26,6 +26,7 @@ import { getTranslationID } from "translation";
import styles from "styles/app.module.scss";
import { getDealersAsync } from "features/signup/operations";
import { LANGUAGE_LIST } from "features/top/constants";
import { openSnackbar } from "features/ui";
import { COUNTRY_LIST } from "./constants";
const SignupInput: React.FC = (): JSX.Element => {
@ -92,7 +93,7 @@ const SignupInput: React.FC = (): JSX.Element => {
// dealer={account_id第四階層のアカウントID} でDealerを指定
// language={language(en/de/fr/es)} で言語を指定
const query = new URLSearchParams(search);
const dealerId = parseInt(query.get("dealer") ?? "", 10);
const paramDealer = query.get("dealer");
const language = query.get("language");
// URLで言語が指定されていたら言語を変更
@ -104,14 +105,30 @@ const SignupInput: React.FC = (): JSX.Element => {
document.cookie = `language=${language}; max-age=31536000`;
}
// URLでDealerが指定されていたら、そのdealerを選択国も選択したDealerの国に変更
if (!Number.isNaN(dealerId)) {
const urlDealer = allDealers.find((x) => x.id === dealerId);
if (urlDealer) {
dispatch(changeCountry({ country: urlDealer.country }));
dispatch(changeDealer({ dealer: urlDealer.id }));
}
// Dealerが取得できていない場合は何もしない
if (allDealers.length === 0) {
return;
}
// URLでDealerが指定されていたら、そのDealerを選択国も選択したDealerの国に変更
const urlDealer = allDealers.find(
(x) => x.id === parseInt(paramDealer ?? "", 10)
);
if (urlDealer) {
dispatch(changeCountry({ country: urlDealer.country }));
dispatch(changeDealer({ dealer: urlDealer.id }));
} else if (paramDealer) {
// URLでDealerが指定されていたが、存在しない場合はメッセージを表示
dispatch(
openSnackbar({
level: "error",
message: t(
getTranslationID("signupPage.message.dealerNotFoundError")
),
})
);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [i18n, dispatch, search, allDealers]);
return (

View File

@ -41,7 +41,8 @@
"message": {
"inputEmptyError": "(de)この項目の入力は必須です。入力してください。",
"passwordIncorrectError": "(de)入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。",
"emailIncorrectError": "(de)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。"
"emailIncorrectError": "(de)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
"dealerNotFoundError": "(de)指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。"
},
"text": {
"title": "(de)Create your account",
@ -330,4 +331,4 @@
"alreadyIssueLicense": "(de)すでに発行済みの注文です。画面を更新してください。"
}
}
}
}

View File

@ -41,7 +41,8 @@
"message": {
"inputEmptyError": "この項目の入力は必須です。入力してください。",
"passwordIncorrectError": "入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。",
"emailIncorrectError": "メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。"
"emailIncorrectError": "メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
"dealerNotFoundError": "指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。"
},
"text": {
"title": "Create your account",
@ -330,4 +331,4 @@
"alreadyIssueLicense": "すでに発行済みの注文です。画面を更新してください。"
}
}
}
}

View File

@ -41,7 +41,8 @@
"message": {
"inputEmptyError": "(es)この項目の入力は必須です。入力してください。",
"passwordIncorrectError": "(es)入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。",
"emailIncorrectError": "(es)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。"
"emailIncorrectError": "(es)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
"dealerNotFoundError": "(es)指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。"
},
"text": {
"title": "(es)Create your account",
@ -330,4 +331,4 @@
"alreadyIssueLicense": "(es)すでに発行済みの注文です。画面を更新してください。"
}
}
}
}

View File

@ -41,7 +41,8 @@
"message": {
"inputEmptyError": "(fr)この項目の入力は必須です。入力してください。",
"passwordIncorrectError": "(fr)入力されたパスワードがルールを満たしていません。下記のルールを満たすパスワードを入力してください。",
"emailIncorrectError": "(fr)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。"
"emailIncorrectError": "(fr)メールアドレスの形式が不正です。正しいメールアドレスの形式で入力してください。",
"dealerNotFoundError": "(fr)指定されたディーラーが見つかりませんでした。直接ディーラーを指定してください。"
},
"text": {
"title": "(fr)Create your account",
@ -330,4 +331,4 @@
"alreadyIssueLicense": "(fr)すでに発行済みの注文です。画面を更新してください。"
}
}
}
}

View File

@ -2027,7 +2027,7 @@
"minLength": 2,
"maxLength": 2
},
"dealerAccountId": { "type": "number", "nullable": true },
"dealerAccountId": { "type": "number" },
"adminName": { "type": "string" },
"adminMail": { "type": "string" },
"adminPassword": { "type": "string" },
@ -2040,7 +2040,6 @@
"required": [
"companyName",
"country",
"dealerAccountId",
"adminName",
"adminMail",
"adminPassword",

View File

@ -125,14 +125,20 @@ export class AccountsService {
context: Context,
companyName: string,
country: string,
dealerAccountId: number | null,
dealerAccountId: number | undefined,
email: string,
password: string,
username: string,
role: string,
acceptedTermsVersion: string,
): Promise<{ accountId: number; userId: number; externalUserId: string }> {
this.logger.log(`[IN] [${context.trackingId}] ${this.createAccount.name}`);
this.logger.log(
`[IN] [${context.trackingId}] ${this.createAccount.name} | params: { ` +
`country: ${country}, ` +
`dealerAccountId: ${dealerAccountId}, ` +
`role: ${role}, ` +
`acceptedTermsVersion: ${acceptedTermsVersion} };`,
);
try {
let externalUser: { sub: string } | ConflictError;
try {
@ -178,6 +184,9 @@ export class AccountsService {
);
account = newAccount;
user = adminUser;
this.logger.log(
`[${context.trackingId}] adminUser.external_id: ${user.external_id}`,
);
} catch (e) {
this.logger.error(`error=${e}`);
this.logger.error('create account failed');

View File

@ -11,10 +11,10 @@ export class CreateAccountRequest {
maxLength: 2,
})
country: string;
@ApiProperty({ nullable: true })
@ApiProperty({ required: false })
@IsInt()
@IsOptional()
dealerAccountId?: number;
dealerAccountId?: number | undefined;
@ApiProperty()
adminName: string;
@ApiProperty()

View File

@ -92,7 +92,7 @@ export class AccountsRepositoryService {
async createAccount(
companyName: string,
country: string,
dealerAccountId: number | null,
dealerAccountId: number | undefined,
tier: number,
adminExternalUserId: string,
adminUserRole: string,