diff --git a/src/controller/userController.ts b/src/controller/userController.ts index b3e0c99..1f3bf1f 100644 --- a/src/controller/userController.ts +++ b/src/controller/userController.ts @@ -119,4 +119,13 @@ export class UserController extends BaseController { { orderId: tickets[0].orderId, refundTicketsCount: tickets.length }, ); }; + + public useTicket: TMethod = async (req) => { + const jwtString = await this.userService.useTicket(req.params.ticketId); + return this.formatResponse( + CustomResponseType.OK_MESSAGE, + CustomResponseType.OK, + { qrCode: jwtString }, + ); + }; } diff --git a/src/routes/userRoute.ts b/src/routes/userRoute.ts index 1914840..9373bf4 100644 --- a/src/routes/userRoute.ts +++ b/src/routes/userRoute.ts @@ -4,6 +4,7 @@ import { UserVerify } from '../middleware/userVerify'; import { GetUserFavoritePipe } from '../validator/user/getUserFavorite.pipe'; import { GetUserGroupPipe } from '../validator/group/getUserGroup.pipe'; import { TicketRefundPipe } from '../validator/ticket/ticketRefund.pipe'; +import { UseTicketPipe } from '../validator/ticket/useTicket.pipe'; export class UserRoute extends BaseRoute { protected controller!: UserController; @@ -278,25 +279,16 @@ export class UserRoute extends BaseRoute { this.router.patch( '/v1/user/refund', /** - * #swagger.tags = ['Ticket'] + * #swagger.tags = ['User'] * #swagger.summary = '退票' * #swagger.security=[{"Bearer": []}] */ /* #swagger.parameters['obj'] ={ in:'body', - description:'欲退票的票券ID', - schema:{ - $ref:"#/definitions/CustomGetTicketIdQuery" - } - } - */ - /* - #swagger.parameters['obj'] ={ - in:'body', - description:'退票原因', + description:'欲退票的票券資料', schema:{ - $ref:"#/definitions/CustomRefundTicketsReason" + $ref:"#/definitions/CustomTicketRefundObj" } } */ @@ -312,5 +304,33 @@ export class UserRoute extends BaseRoute { this.usePipe(TicketRefundPipe), this.responseHandler(this.controller.ticketRefund), ); + + this.router.post( + '/v1/user/use-ticket/:ticketId', + /** + * #swagger.tags = ['User'] + * #swagger.summary = '產生換票QR Code' + * #swagger.security=[{"Bearer": []}] + */ + /* + #swagger.parameters['ticketId'] ={ + in:'path', + description:'欲兌換的票券ID', + required: true, + type: 'string', + } + */ + /** + #swagger.responses[200]={ + description:'QR Code產生成功', + schema:{ + $ref:'#/definitions/GetQRCodeSuccess' + } + } + */ + UserVerify, + this.usePipe(UseTicketPipe), + this.responseHandler(this.controller.useTicket), + ); } } diff --git a/src/service/userService.ts b/src/service/userService.ts index 25456eb..df1a761 100644 --- a/src/service/userService.ts +++ b/src/service/userService.ts @@ -108,17 +108,6 @@ export class UserService { return user; } - public async findByEmail(email: string) { - const user = await this.userRepository.findByEmail(email); - if (!user) { - throwError( - CustomResponseType.UNREGISTERED_USER_MESSAGE, - CustomResponseType.UNREGISTERED_USER, - ); - } - return user; - } - public async getUserGroups(getUserGroupDto: GetUserGroupDto) { switch (getUserGroupDto.groupType) { case 'own': { @@ -416,4 +405,25 @@ export class UserService { }); return result; } + + public useTicket = async (ticketId: string) => { + const ticket = await this.ticketRepository.findById( + new Types.ObjectId(ticketId), + ); + if (!ticket) { + throwError( + CustomResponseType.TICKET_NOT_FOUND_MESSAGE, + CustomResponseType.TICKET_NOT_FOUND, + ); + } + const privateKey = process.env.JWT_SECRETS; + const defaultOptions: object = { + expiresIn: '5m', + }; + return jwt.sign( + { ticketId: ticketId }, + privateKey, + Object.assign(defaultOptions), + ); + }; } diff --git a/src/swagger/definition/ticket/custom.ts b/src/swagger/definition/ticket/custom.ts index 62e3861..9607016 100644 --- a/src/swagger/definition/ticket/custom.ts +++ b/src/swagger/definition/ticket/custom.ts @@ -146,3 +146,19 @@ export const CustomDeleteTicketsObj = { }, }, }; +export const CustomTicketRefundObj = { + type: 'object', + required: ['ticketId', 'reason'], + properties: { + ticketId: { + type: 'string', + description: propName.ticketId, + example: ticket.ticketId, + }, + reason: { + type: 'string', + description: '退票原因', + example: '臨時有事', + }, + }, +}; diff --git a/src/swagger/definition/ticket/general.ts b/src/swagger/definition/ticket/general.ts index 86f1a0b..f63f605 100644 --- a/src/swagger/definition/ticket/general.ts +++ b/src/swagger/definition/ticket/general.ts @@ -14,6 +14,10 @@ const TicketProductDetail = { photoPath: '', }; +const QRCodeResponse = { + qrCode: 'uwiehdfipu28349y5rp24gh9', +}; + /** * @description swagger autogen 可以自動生成,通常用於 response 的 general 資料 */ @@ -130,3 +134,9 @@ export const GetTransferTicketSuccess = { $message: CustomResponseType.OK_MESSAGE, $data: [TransferableTicket], }; + +export const GetQRCodeSuccess = { + $status: CustomResponseType.OK, + $message: CustomResponseType.OK_MESSAGE, + $data: QRCodeResponse, +}; diff --git a/src/validator/ticket/useTicket.pipe.ts b/src/validator/ticket/useTicket.pipe.ts new file mode 100644 index 0000000..29f37cb --- /dev/null +++ b/src/validator/ticket/useTicket.pipe.ts @@ -0,0 +1,17 @@ +import { param } from 'express-validator'; +import { PipeBase } from '../pipe.base'; +import { CustomResponseType } from '../../types/customResponseType'; + +export class UseTicketPipe extends PipeBase { + public transform = () => [ + param('ticketId') + .exists() + .withMessage( + CustomResponseType.INVALID_TICKET_REFUND_MESSAGE + 'ticketId', + ), + this.validationHandler, + ]; + constructor() { + super(); + } +}