feat: add subscription

This commit is contained in:
Nevo David 2024-08-13 12:42:19 +07:00
parent 52d93d8a51
commit cb30d5e324
4 changed files with 97 additions and 5 deletions

View File

@ -2,9 +2,10 @@ import { Body, Controller, Get, Param, Post } 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 } from '@prisma/client';
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';
@ApiTags('Billing')
@Controller('/billing')
@ -71,4 +72,17 @@ export class BillingController {
) {
return this._stripeService.lifetimeDeal(org.id, body.code);
}
@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);
}
}

View File

@ -1,9 +1,55 @@
import { Input } from '@gitroom/react/form/input';
import { useCallback, useMemo, useState } from 'react';
import { ChangeEventHandler, useCallback, useMemo, useState } from 'react';
import useSWR from 'swr';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { useUser } from '@gitroom/frontend/components/layout/user.context';
import { Select } from '@gitroom/react/form/select';
import { pricing } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/pricing';
import { deleteDialog } from '@gitroom/react/helpers/delete.dialog';
export const Subscription = () => {
const fetch = useFetch();
const addSubscription: ChangeEventHandler<HTMLSelectElement> = useCallback(
async (e) => {
const value = e.target.value;
if (
await deleteDialog(
'Are you sure you want to add a user subscription?',
'Add'
)
) {
await fetch('/billing/add-subscription', {
method: 'POST',
body: JSON.stringify({ subscription: value }),
});
window.location.reload();
}
},
[]
);
return (
<Select
onChange={addSubscription}
hideErrors={true}
disableForm={true}
name="sub"
label=""
value=""
className="text-black"
>
<option>-- ADD FREE SUBSCRIPTION --</option>
{Object.keys(pricing)
.filter((f) => !f.includes('FREE'))
.map((key) => (
<option key={key} value={key}>
{key}
</option>
))}
</Select>
);
};
export const Impersonate = () => {
const fetch = useFetch();
const [name, setName] = useState('');
@ -76,6 +122,7 @@ export const Impersonate = () => {
X
</div>
</div>
{user?.tier?.current === 'FREE' && <Subscription />}
</div>
) : (
<Input

View File

@ -202,4 +202,15 @@ export class SubscriptionRepository {
},
});
}
setCustomerId(orgId: string, customerId: string) {
return this._organization.model.organization.update({
where: {
id: orgId,
},
data: {
paymentId: customerId,
},
});
}
}

View File

@ -5,6 +5,7 @@ import { IntegrationService } from '@gitroom/nestjs-libraries/database/prisma/in
import { OrganizationService } from '@gitroom/nestjs-libraries/database/prisma/organizations/organization.service';
import { Organization } from '@prisma/client';
import dayjs from 'dayjs';
import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
@Injectable()
export class SubscriptionService {
@ -164,7 +165,7 @@ export class SubscriptionService {
const type = organization?.subscription?.subscriptionTier || 'FREE';
if (type === 'FREE') {
return {credits: 0};
return { credits: 0 };
}
// @ts-ignore
@ -176,10 +177,29 @@ export class SubscriptionService {
const checkFromMonth = date.subtract(1, 'month');
const imageGenerationCount = pricing[type].image_generation_count;
const totalUse = await this._subscriptionRepository.getCreditsFrom(organization.id, checkFromMonth);
const totalUse = await this._subscriptionRepository.getCreditsFrom(
organization.id,
checkFromMonth
);
return {
credits: imageGenerationCount - totalUse,
}
};
}
async addSubscription(orgId: string, userId: string, subscription: any) {
await this._subscriptionRepository.setCustomerId(orgId, orgId);
return this.createOrUpdateSubscription(
makeId(5),
userId,
pricing[subscription].channel!,
subscription,
'MONTHLY',
null,
undefined,
orgId
);
}
}