[TIL] Work-Flow 프로젝트 - Membership, payment (2/4) 23.08.28

이상훈·2023년 8월 29일
0

[내일배움캠프]

목록 보기
60/68
 // 결제 취소
  async cancelPurchase(workspaceId: number, paymentId: number, userId: number): Promise<Object> {
    const entityManager = this.paymentRepository.manager;

    const targetPayment = await this.paymentRepository.findOne({
      where: { id: paymentId, workspaceId, user: { id: userId } },
    });
    if (!targetPayment) throw new HttpException('해당 결제 내역을 찾을 수 없습니다.', HttpStatus.NOT_FOUND);

    const targetMembership = await this.membershipService.getMyMembership(workspaceId);

    const milliSecondPerDay = 24 * 60 * 60 * 1000;
    const refundRequestDate = new Date();

    // 남은기간 계산
    const remainingTime = targetMembership.end_date.getTime() - refundRequestDate.getTime();
    const remainingDays = Math.floor(remainingTime / milliSecondPerDay);

    // 멤버십 금액의 일할 계산
    const membershipPeriod = targetMembership.end_date.getTime() - targetMembership.created_at.getTime();
    const daysInMembership = Math.floor(membershipPeriod / milliSecondPerDay);

    const dailyPrice = Math.floor(targetMembership.package_price / daysInMembership);
    const refundPrice = Math.floor(remainingDays) * dailyPrice;
    const roundedRefundPrice = Math.floor(refundPrice / 100) * 100;

    await entityManager.transaction(async (transactionEntityManager: EntityManager) => {
      await this.membershipService.cancelMembership(workspaceId);

      targetPayment.status = false;
      await transactionEntityManager.save(targetPayment);

      const user = await this.userService.findUserById(userId);
      const refundPoint = roundedRefundPrice;
      const remainPoint = (user.points += refundPoint);
      await transactionEntityManager.save(User, { ...user, points: remainPoint });
    });
    return { remainingDays, roundedRefundPrice };
  }

생성과 마찬가지로 트랜잭션을 생성, 취소하려는 결제와 멤버십을 조회하고 해당 멤버십의 남은 기간을 계산해줌
남은 기간에 일할계산 된 금액을 곱하고 환불금액을 유저포인트에 다시 넣어준 뒤 커밋

  • 멤버십 가입 후 취소 테스트
 console.log(remainingDays); // 179
 console.log(dailyPrice); // 173
 console.log(refundPrice); // 30967
 console.log(roundedRefundPrice); // 30900

금액이 정확히 일치하진 않지만 정상적으로 환불되는 것을 확인

  // 멤버십 취소
  async cancelMembership(workspaceId: number): Promise<IResult> {
    const targetMembership = await this.membershipRepository.findOne({ where: { workspace: { id: workspaceId } } });

    if (!targetMembership) throw new HttpException('결제된 멤버십이 없습니다.', HttpStatus.NOT_FOUND);

    await this.membershipRepository.remove(targetMembership);

    return { result: true };
  }

결제내역 조회를 위해 payment는 status만 false로 바꿔주고 삭제하지 않음

  // 나의 결제내역 조회
  async getMyPayments(userId: number): Promise<Payment[]> {
    const payments = await this.paymentRepository.find({ where: { user: { id: userId } }, relations: ['user'] });
    const paymentHistory = [];
    for (const payment of payments) {
      const workspaceId = payment.workspaceId;
      const workspace = await this.workspaceService.getWorkspaceDetail(workspaceId);

      if (workspace.memberships.length > 0) {
        const membership = workspace.memberships[0];
        const paymentInfo = {
          paymentId: payment.id,
          paymentCreatedAt: payment.created_at,
          workspaceId,
          workspaceName: workspace.name,
          membershipCreatedAt: membership.created_at,
          membershipEndDate: membership.end_date,
          membershipPrice: membership.package_price,
        };
        paymentHistory.push(paymentInfo);
      } else {
        const paymentInfo = {
          paymentId: payment.id,
          paymentCreatedAt: payment.created_at,
          workspaceId,
          workspaceName: workspace.name,
        };
        paymentHistory.push(paymentInfo);
      }
    }
    return paymentHistory;
  }

paymentHistory 빈배열을 만들고 워크스페이스에 멤버십이 있다면 멤버십의 정보를 출력해주고 아니라면 취소된 결제라 판단

발생한 문제

취소된 결제가 존재할 때 새로운 멤버십을 결제하는 경우

아래 취소되었던 멤버십도 같이 활성화되는 문제를 발견

profile
코린이

0개의 댓글