From 3308133736668f7748fb8754ed51a138a3a89180 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Sun, 22 Sep 2024 14:55:48 +0200 Subject: [PATCH] feat: Edit Stripe payment settings --- .../PaymentServicesController.ts | 28 +++++++++++++++++++ .../PaymentServices/GetPaymentService.ts | 27 ++++++++++++++++++ .../PaymentServicesApplication.ts | 16 +++++++++++ .../PreferencesPaymentMethodsPage.tsx | 3 +- .../drawers/StripeIntegrationEditBoot.tsx | 19 +++++++++++-- .../drawers/StripeIntegrationEditForm.tsx | 10 ++++++- .../src/hooks/query/payment-services.ts | 21 ++++++++++++++ 7 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 packages/server/src/services/PaymentServices/GetPaymentService.ts diff --git a/packages/server/src/api/controllers/PaymentServices/PaymentServicesController.ts b/packages/server/src/api/controllers/PaymentServices/PaymentServicesController.ts index 11be0f93a..10abdfc63 100644 --- a/packages/server/src/api/controllers/PaymentServices/PaymentServicesController.ts +++ b/packages/server/src/api/controllers/PaymentServices/PaymentServicesController.ts @@ -21,6 +21,7 @@ export class PaymentServicesController extends BaseController { asyncMiddleware(this.getPaymentServicesSpecificInvoice.bind(this)) ); router.get('/state', this.getPaymentMethodsState.bind(this)); + router.get('/:paymentServiceId', this.getPaymentService.bind(this)); router.post( '/:paymentMethodId', [ @@ -65,6 +66,33 @@ export class PaymentServicesController extends BaseController { } } + /** + * Retrieves a specific payment service. + * @param {Request} req - Request. + * @param {Response} res - Response. + * @param {NextFunction} next - Next function. + * @return {Promise} + */ + private async getPaymentService( + req: Request<{ paymentServiceId: number }>, + res: Response, + next: NextFunction + ) { + const { tenantId } = req; + const { paymentServiceId } = req.params; + + try { + const paymentService = await this.paymentServicesApp.getPaymentService( + tenantId, + paymentServiceId + ); + + return res.status(200).send({ data: paymentService }); + } catch (error) { + next(error); + } + } + /** * Edits the given payment method settings. * @param {Request} req - Request. diff --git a/packages/server/src/services/PaymentServices/GetPaymentService.ts b/packages/server/src/services/PaymentServices/GetPaymentService.ts new file mode 100644 index 000000000..35557c46a --- /dev/null +++ b/packages/server/src/services/PaymentServices/GetPaymentService.ts @@ -0,0 +1,27 @@ +import { Inject, Service } from 'typedi'; +import HasTenancyService from '../Tenancy/TenancyService'; +import { GetPaymentMethodsPOJO } from './types'; + +@Service() +export class GetPaymentMethodService { + @Inject() + private tenancy: HasTenancyService; + + /** + * Retrieves the payment state provising state. + * @param {number} tenantId + * @returns {Promise} + */ + public async getPaymentMethod( + tenantId: number, + paymentServiceId: number + ): Promise { + const { PaymentIntegration } = this.tenancy.models(tenantId); + + const stripePayment = await PaymentIntegration.query() + .findById(paymentServiceId) + .throwIfNotFound(); + + return stripePayment; + } +} diff --git a/packages/server/src/services/PaymentServices/PaymentServicesApplication.ts b/packages/server/src/services/PaymentServices/PaymentServicesApplication.ts index 4e453547b..b062b4bb9 100644 --- a/packages/server/src/services/PaymentServices/PaymentServicesApplication.ts +++ b/packages/server/src/services/PaymentServices/PaymentServicesApplication.ts @@ -4,6 +4,7 @@ import { DeletePaymentMethodService } from './DeletePaymentMethodService'; import { EditPaymentMethodService } from './EditPaymentMethodService'; import { EditPaymentMethodDTO, GetPaymentMethodsPOJO } from './types'; import { GetPaymentMethodsStateService } from './GetPaymentMethodsState'; +import { GetPaymentMethodService } from './GetPaymentService'; @Service() export class PaymentServicesApplication { @@ -19,6 +20,9 @@ export class PaymentServicesApplication { @Inject() private getPaymentMethodsStateService: GetPaymentMethodsStateService; + @Inject() + private getPaymentMethodService: GetPaymentMethodService; + /** * Retrieves the payment services for a specific invoice. * @param {number} tenantId - The ID of the tenant. @@ -31,6 +35,18 @@ export class PaymentServicesApplication { ); } + /** + * Retrieves specific payment service details. + * @param {number} tenantId - Tennat id. + * @param {number} paymentServiceId - Payment service id. + */ + public async getPaymentService(tenantId: number, paymentServiceId: number) { + return this.getPaymentMethodService.getPaymentMethod( + tenantId, + paymentServiceId + ); + } + /** * Deletes the given payment method. * @param {number} tenantId diff --git a/packages/webapp/src/containers/Preferences/PaymentMethods/PreferencesPaymentMethodsPage.tsx b/packages/webapp/src/containers/Preferences/PaymentMethods/PreferencesPaymentMethodsPage.tsx index 960f4d279..07b86277f 100644 --- a/packages/webapp/src/containers/Preferences/PaymentMethods/PreferencesPaymentMethodsPage.tsx +++ b/packages/webapp/src/containers/Preferences/PaymentMethods/PreferencesPaymentMethodsPage.tsx @@ -91,10 +91,12 @@ function StripePaymentMethod() { }); }; + // Handle edit button click. const handleEditBtnClick = () => { openDrawer(DRAWERS.STRIPE_PAYMENT_INTEGRATION_EDIT); }; + // Handle delete connection button click. const handleDeleteConnectionClick = () => { openAlert('delete-stripe-payment-method', { paymentMethodId: stripePaymentMethodId, @@ -133,7 +135,6 @@ function StripePaymentMethod() { Complete Stripe Set Up )} - {isAccountCreated && ( { export const StripeIntegrationEditBoot: React.FC = ({ children }) => { const { data: accounts, isLoading: isAccountsLoading } = useAccounts({}, {}); - const value = { accounts, isAccountsLoading }; - const isLoading = isAccountsLoading; + const { data: paymentMethod, isLoading: isPaymentMethodLoading } = + useGetPaymentMethod(9); + + const value = { + // Accounts. + accounts, + isAccountsLoading, + + // Payment methods. + paymentMethod, + isPaymentMethodLoading, + }; + const isLoading = isAccountsLoading || isPaymentMethodLoading; if (isLoading) { return ; diff --git a/packages/webapp/src/containers/Preferences/PaymentMethods/drawers/StripeIntegrationEditForm.tsx b/packages/webapp/src/containers/Preferences/PaymentMethods/drawers/StripeIntegrationEditForm.tsx index 33f9124ca..4aecfa892 100644 --- a/packages/webapp/src/containers/Preferences/PaymentMethods/drawers/StripeIntegrationEditForm.tsx +++ b/packages/webapp/src/containers/Preferences/PaymentMethods/drawers/StripeIntegrationEditForm.tsx @@ -7,6 +7,8 @@ import { Intent } from '@blueprintjs/core'; import { usePaymentMethodsBoot } from '../PreferencesPaymentMethodsBoot'; import { useDrawerActions } from '@/hooks/state'; import { useDrawerContext } from '@/components/Drawer/DrawerProvider'; +import { useStripeIntegrationEditBoot } from './StripeIntegrationEditBoot'; +import { transformToForm } from '@/utils'; interface StripeIntegrationFormValues { paymentAccountId: string; @@ -34,9 +36,15 @@ export function StripeIntegrationEditForm({ const { name } = useDrawerContext(); const { mutateAsync: updatePaymentMethod } = useUpdatePaymentMethod(); const { paymentMethodsState } = usePaymentMethodsBoot(); + const { paymentMethod } = useStripeIntegrationEditBoot(); const stripePaymentState = paymentMethodsState?.stripe; const paymentMethodId = stripePaymentState?.stripePaymentMethodId; + const formInitialValues = { + ...initialValues, + ...transformToForm(paymentMethod?.options, initialValues), + }; + const onSubmit = ( values: StripeIntegrationFormValues, { setSubmitting }: FormikHelpers, @@ -62,7 +70,7 @@ export function StripeIntegrationEditForm({ return ( diff --git a/packages/webapp/src/hooks/query/payment-services.ts b/packages/webapp/src/hooks/query/payment-services.ts index d9eef51b9..5312944dd 100644 --- a/packages/webapp/src/hooks/query/payment-services.ts +++ b/packages/webapp/src/hooks/query/payment-services.ts @@ -114,3 +114,24 @@ export const useUpdatePaymentMethod = (): UseMutationResult< .then((response) => response.data), ); }; + +interface GetPaymentMethodResponse {} +/** + * Retrieves a specific payment method. + * @param {number} paymentMethodId - The ID of the payment method. + * @returns {UseQueryResult} + */ +export const useGetPaymentMethod = ( + paymentMethodId: number, +): UseQueryResult => { + const apiRequest = useApiRequest(); + + return useQuery( + ['paymentMethod', paymentMethodId], + () => apiRequest.get(`/payment-services/${paymentMethodId}`), + { + select: (data) => + transformToCamelCase(data.data) as GetPaymentMethodResponse, + }, + ); +};