| import { Body, Controller, Get, HttpException, Param, Post, Req } from '@nestjs/common'; |
| import { SubscriptionService } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/subscription.service'; |
| import { StripeService } from '@gitroom/nestjs-libraries/services/stripe.service'; |
| import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request'; |
| import { Organization, User } from '@prisma/client'; |
| import { BillingSubscribeDto } from '@gitroom/nestjs-libraries/dtos/billing/billing.subscribe.dto'; |
| import { ApiTags } from '@nestjs/swagger'; |
| import { GetUserFromRequest } from '@gitroom/nestjs-libraries/user/user.from.request'; |
| import { NotificationService } from '@gitroom/nestjs-libraries/database/prisma/notifications/notification.service'; |
| import { Request } from 'express'; |
| import { AuthService } from '@gitroom/helpers/auth/auth.service'; |
|
|
| @ApiTags('Billing') |
| @Controller('/billing') |
| export class BillingController { |
| constructor( |
| private _subscriptionService: SubscriptionService, |
| private _stripeService: StripeService, |
| private _notificationService: NotificationService |
| ) {} |
|
|
| @Get('/check/:id') |
| async checkId( |
| @GetOrgFromRequest() org: Organization, |
| @Param('id') body: string |
| ) { |
| return { |
| status: await this._stripeService.checkSubscription(org.id, body), |
| }; |
| } |
|
|
| @Get('/check-discount') |
| async checkDiscount(@GetOrgFromRequest() org: Organization) { |
| return { |
| offerCoupon: !(await this._stripeService.checkDiscount(org.paymentId)) |
| ? false |
| : AuthService.signJWT({ discount: true }), |
| }; |
| } |
|
|
| @Post('/apply-discount') |
| async applyDiscount(@GetOrgFromRequest() org: Organization) { |
| await this._stripeService.applyDiscount(org.paymentId); |
| } |
|
|
| @Post('/finish-trial') |
| async finishTrial(@GetOrgFromRequest() org: Organization) { |
| try { |
| await this._stripeService.finishTrial(org.paymentId); |
| } catch (err) {} |
| return { |
| finish: true, |
| }; |
| } |
|
|
| @Get('/is-trial-finished') |
| async isTrialFinished(@GetOrgFromRequest() org: Organization) { |
| return { |
| finished: !org.isTrailing, |
| }; |
| } |
|
|
| @Post('/embedded') |
| embedded( |
| @GetOrgFromRequest() org: Organization, |
| @GetUserFromRequest() user: User, |
| @Body() body: BillingSubscribeDto, |
| @Req() req: Request |
| ) { |
| const uniqueId = req?.cookies?.track; |
| return this._stripeService.embedded( |
| uniqueId, |
| org.id, |
| user.id, |
| body, |
| org.allowTrial |
| ); |
| } |
|
|
| @Post('/subscribe') |
| subscribe( |
| @GetOrgFromRequest() org: Organization, |
| @GetUserFromRequest() user: User, |
| @Body() body: BillingSubscribeDto, |
| @Req() req: Request |
| ) { |
| const uniqueId = req?.cookies?.track; |
| return this._stripeService.subscribe( |
| uniqueId, |
| org.id, |
| user.id, |
| body, |
| org.allowTrial |
| ); |
| } |
|
|
| @Get('/portal') |
| async modifyPayment(@GetOrgFromRequest() org: Organization) { |
| const customer = await this._stripeService.getCustomerByOrganizationId( |
| org.id |
| ); |
| const { url } = await this._stripeService.createBillingPortalLink(customer); |
| return { |
| portal: url, |
| }; |
| } |
|
|
| @Get('/') |
| getCurrentBilling(@GetOrgFromRequest() org: Organization) { |
| return this._subscriptionService.getSubscriptionByOrganizationId(org.id); |
| } |
|
|
| @Post('/cancel') |
| async cancel( |
| @GetOrgFromRequest() org: Organization, |
| @GetUserFromRequest() user: User, |
| @Body() body: { feedback: string } |
| ) { |
| await this._notificationService.sendEmail( |
| process.env.EMAIL_FROM_ADDRESS, |
| 'Subscription Cancelled', |
| `Organization ${org.name} has cancelled their subscription because: ${body.feedback}`, |
| user.email |
| ); |
|
|
| return this._stripeService.setToCancel(org.id); |
| } |
|
|
| @Post('/prorate') |
| prorate( |
| @GetOrgFromRequest() org: Organization, |
| @Body() body: BillingSubscribeDto |
| ) { |
| return this._stripeService.prorate(org.id, body); |
| } |
|
|
| @Get('/charges') |
| async getCharges( |
| @GetUserFromRequest() user: User, |
| @GetOrgFromRequest() org: Organization |
| ) { |
| if (!user.isSuperAdmin) { |
| throw new HttpException('Unauthorized', 400); |
| } |
|
|
| return this._stripeService.getCharges(org.id); |
| } |
|
|
| @Post('/refund-charges') |
| async refundCharges( |
| @GetUserFromRequest() user: User, |
| @GetOrgFromRequest() org: Organization, |
| @Body() body: { chargeIds: string[] } |
| ) { |
| if (!user.isSuperAdmin) { |
| throw new HttpException('Unauthorized', 400); |
| } |
|
|
| return this._stripeService.refundCharges(org.id, body.chargeIds); |
| } |
|
|
| @Post('/cancel-subscription') |
| async cancelSubscription( |
| @GetUserFromRequest() user: User, |
| @GetOrgFromRequest() org: Organization |
| ) { |
| if (!user.isSuperAdmin) { |
| throw new HttpException('Unauthorized', 400); |
| } |
|
|
| return this._stripeService.cancelSubscription(org.id); |
| } |
|
|
| @Get('/chatbase-refund/preview') |
| chatbaseRefundPreview(@GetOrgFromRequest() org: Organization) { |
| return this._stripeService.chatbaseRefundPreview(org.id); |
| } |
|
|
| @Post('/chatbase-refund') |
| async chatbaseRefund( |
| @GetUserFromRequest() user: User, |
| @GetOrgFromRequest() org: Organization |
| ) { |
| const refund = await this._stripeService.chatbaseRefund(org.id); |
|
|
| if (refund.refunded) { |
| await this._notificationService.sendEmail( |
| process.env.EMAIL_FROM_ADDRESS, |
| 'Refund issued from Chatbase', |
| `Organization ${org.name} received a refund of ${refund.amount} ${refund.currency} and their subscription was cancelled`, |
| user.email |
| ); |
| } |
|
|
| return refund; |
| } |
|
|
| @Post('/add-subscription') |
| async addSubscription( |
| @Body() body: { subscription: string }, |
| @GetUserFromRequest() user: User, |
| @GetOrgFromRequest() org: Organization |
| ) { |
| if (!user.isSuperAdmin) { |
| throw new Error('Unauthorized'); |
| } |
|
|
| await this._subscriptionService.addSubscription( |
| org.id, |
| user.id, |
| body.subscription |
| ); |
| } |
|
|
| } |
|
|