Merged PR 349: API実装(ライセンス割り当て解除API)
## 概要 [Task2450: API実装(ライセンス割り当て解除API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2450) ライセンス割り当て解除APIを実装しました。 ## レビューポイント なし ## UIの変更 なし ## 動作確認状況 ローカルでUT、動作確認済み ## 補足 なし
This commit is contained in:
parent
177c8beb41
commit
0fd1ff2b6a
@ -46,4 +46,5 @@ export const ErrorCodes = [
|
||||
'E010804', // ライセンス不足エラー
|
||||
'E010805', // ライセンス有効期限切れエラー
|
||||
'E010806', // ライセンス割り当て不可エラー
|
||||
'E010807', // ライセンス割り当て解除済みエラー
|
||||
] as const;
|
||||
|
||||
@ -35,4 +35,5 @@ export const errors: Errors = {
|
||||
E010804: 'License shortage Error',
|
||||
E010805: 'License is expired Error',
|
||||
E010806: 'License is unavailable Error',
|
||||
E010807: 'License is already deallocated Error',
|
||||
};
|
||||
|
||||
@ -844,3 +844,107 @@ describe('ライセンス割り当て', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ライセンス割り当て解除', () => {
|
||||
let source: DataSource = null;
|
||||
beforeEach(async () => {
|
||||
source = new DataSource({
|
||||
type: 'sqlite',
|
||||
database: ':memory:',
|
||||
logging: false,
|
||||
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
|
||||
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
|
||||
});
|
||||
return source.initialize();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await source.destroy();
|
||||
source = null;
|
||||
});
|
||||
|
||||
it('ライセンスの割り当て解除が完了する', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
|
||||
const { accountId } = await createAccount(source);
|
||||
const { userId } = await createUser(source, accountId, 'userId', 'admin');
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() + 30);
|
||||
await createLicense(
|
||||
source,
|
||||
1,
|
||||
date,
|
||||
accountId,
|
||||
LICENSE_TYPE.NORMAL,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
userId,
|
||||
);
|
||||
await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE');
|
||||
|
||||
const service = module.get<UsersService>(UsersService);
|
||||
await service.deallocateLicense(makeContext('trackingId'), userId);
|
||||
|
||||
// 割り当て解除したライセンスの状態確認
|
||||
const deallocatedLicense = await selectLicense(source, 1);
|
||||
expect(deallocatedLicense.license.allocated_user_id).toBe(null);
|
||||
expect(deallocatedLicense.license.status).toBe(
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
);
|
||||
expect(deallocatedLicense.license.expiry_date).toEqual(date);
|
||||
|
||||
// ライセンス履歴テーブルの状態確認
|
||||
const licenseAllocationHistory = await selectLicenseAllocationHistory(
|
||||
source,
|
||||
userId,
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.user_id).toBe(
|
||||
userId,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.license_id).toBe(
|
||||
1,
|
||||
);
|
||||
expect(licenseAllocationHistory.licenseAllocationHistory.is_allocated).toBe(
|
||||
false,
|
||||
);
|
||||
expect(
|
||||
licenseAllocationHistory.licenseAllocationHistory.switch_from_type,
|
||||
).toBe('NONE');
|
||||
});
|
||||
|
||||
it('ライセンスが既に割り当て解除されていた場合、エラーとなる', async () => {
|
||||
const module = await makeTestingModule(source);
|
||||
|
||||
const { accountId } = await createAccount(source);
|
||||
const { userId } = await createUser(source, accountId, 'userId', 'admin');
|
||||
await createUser(source, accountId, 'userId2', 'admin');
|
||||
const date = new Date();
|
||||
date.setDate(date.getDate() + 30);
|
||||
await createLicense(
|
||||
source,
|
||||
1,
|
||||
date,
|
||||
accountId,
|
||||
LICENSE_TYPE.NORMAL,
|
||||
LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
2,
|
||||
);
|
||||
await createLicense(
|
||||
source,
|
||||
2,
|
||||
date,
|
||||
accountId,
|
||||
LICENSE_TYPE.NORMAL,
|
||||
LICENSE_ALLOCATED_STATUS.REUSABLE,
|
||||
userId,
|
||||
);
|
||||
await createLicenseAllocationHistory(source, 1, userId, 1, 'NONE');
|
||||
|
||||
const service = module.get<UsersService>(UsersService);
|
||||
await expect(
|
||||
service.deallocateLicense(makeContext('trackingId'), userId),
|
||||
).rejects.toEqual(
|
||||
new HttpException(makeErrorResponse('E010807'), HttpStatus.BAD_REQUEST),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -461,13 +461,12 @@ export class UsersController {
|
||||
@Body() body: DeallocateLicenseRequest,
|
||||
@Req() req: Request,
|
||||
): Promise<DeallocateLicenseResponse> {
|
||||
//API実装時に詳細をかいていく
|
||||
//const accessToken = retrieveAuthorizationToken(req);
|
||||
//const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
const accessToken = retrieveAuthorizationToken(req);
|
||||
const { userId } = jwt.decode(accessToken, { json: true }) as AccessToken;
|
||||
|
||||
//const context = makeContext(userId);
|
||||
const context = makeContext(userId);
|
||||
|
||||
//await this.usersService.deallocateLicense(context, body.userId);
|
||||
await this.usersService.deallocateLicense(context, body.userId);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,7 @@ import { DateWithZeroTime } from '../licenses/types/types';
|
||||
import { Context } from '../../common/log';
|
||||
import { UserRoles } from '../../common/types/role';
|
||||
import {
|
||||
LicenseAlreadyDeallocatedError,
|
||||
LicenseExpiredError,
|
||||
LicenseUnavailableError,
|
||||
} from '../../repositories/licenses/errors/types';
|
||||
@ -886,7 +887,7 @@ export class UsersService {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.allocateLicense.name} | params: { ` +
|
||||
`userId: ${userId}, ` +
|
||||
`newLicenseId: ${newLicenseId}, `,
|
||||
`newLicenseId: ${newLicenseId}, };`,
|
||||
);
|
||||
|
||||
try {
|
||||
@ -918,4 +919,40 @@ export class UsersService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーに割り当てられているライセンスを解除します
|
||||
* @param context
|
||||
* @param userId
|
||||
*/
|
||||
async deallocateLicense(context: Context, userId: number): Promise<void> {
|
||||
this.logger.log(
|
||||
`[IN] [${context.trackingId}] ${this.deallocateLicense.name} | params: { ` +
|
||||
`userId: ${userId}, };`,
|
||||
);
|
||||
|
||||
try {
|
||||
await this.licensesRepository.deallocateLicense(userId);
|
||||
} catch (e) {
|
||||
this.logger.error(`error=${e}`);
|
||||
if (e instanceof Error) {
|
||||
switch (e.constructor) {
|
||||
case LicenseAlreadyDeallocatedError:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E010807'),
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
default:
|
||||
throw new HttpException(
|
||||
makeErrorResponse('E009999'),
|
||||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.logger.log(
|
||||
`[OUT] [${context.trackingId}] ${this.deallocateLicense.name}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,3 +18,6 @@ export class LicensesShortageError extends Error {}
|
||||
export class LicenseExpiredError extends Error {}
|
||||
// ライセンス割り当て不可エラー
|
||||
export class LicenseUnavailableError extends Error {}
|
||||
|
||||
// ライセンス割り当て解除済みエラー
|
||||
export class LicenseAlreadyDeallocatedError extends Error {}
|
||||
|
||||
@ -25,6 +25,7 @@ import {
|
||||
OrderNotFoundError,
|
||||
LicenseExpiredError,
|
||||
LicenseUnavailableError,
|
||||
LicenseAlreadyDeallocatedError,
|
||||
} from './errors/types';
|
||||
import {
|
||||
AllocatableLicenseInfo,
|
||||
@ -541,4 +542,45 @@ export class LicensesRepositoryService {
|
||||
await licenseAllocationHistoryRepo.save(allocationHistory);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ユーザーに割り当てられているライセンスを解除する
|
||||
* @param userId
|
||||
*/
|
||||
async deallocateLicense(userId: number): Promise<void> {
|
||||
await this.dataSource.transaction(async (entityManager) => {
|
||||
const licenseRepo = entityManager.getRepository(License);
|
||||
const licenseAllocationHistoryRepo = entityManager.getRepository(
|
||||
LicenseAllocationHistory,
|
||||
);
|
||||
// 対象ユーザーのライセンス割り当て状態を取得
|
||||
const allocatedLicense = await licenseRepo.findOne({
|
||||
where: {
|
||||
allocated_user_id: userId,
|
||||
status: LICENSE_ALLOCATED_STATUS.ALLOCATED,
|
||||
},
|
||||
});
|
||||
|
||||
// ライセンスが割り当てられていない場合はエラー
|
||||
if (!allocatedLicense) {
|
||||
throw new LicenseAlreadyDeallocatedError(
|
||||
`License is already deallocated. userId: ${userId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// ライセンスの割り当てを解除
|
||||
allocatedLicense.status = LICENSE_ALLOCATED_STATUS.REUSABLE;
|
||||
allocatedLicense.allocated_user_id = null;
|
||||
await licenseRepo.save(allocatedLicense);
|
||||
|
||||
// ライセンス割り当て履歴テーブルへ登録
|
||||
const deallocationHistory = new LicenseAllocationHistory();
|
||||
deallocationHistory.user_id = userId;
|
||||
deallocationHistory.license_id = allocatedLicense.id;
|
||||
deallocationHistory.is_allocated = false;
|
||||
deallocationHistory.executed_at = new Date();
|
||||
deallocationHistory.switch_from_type = SWITCH_FROM_TYPE.NONE;
|
||||
await licenseAllocationHistoryRepo.save(deallocationHistory);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user