1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-11-28 09:24:24 +01:00

optimized the load time of the payment schedules list

From now, we no longer retrieve the client_secret directly from the API/list but from a specialized component which ask API/get_item.
This highly decrease the laod time needed to fetch API/list
This commit is contained in:
Sylvain 2022-01-03 11:24:08 +01:00
parent bfb1a1c3f9
commit effe5c7ba9
13 changed files with 94 additions and 15 deletions

View File

@ -1,6 +1,7 @@
# Changelog Fab-manager
- Updated caniuse db
- Optimized the load time of the payment schedules list
# v5.3.0 2021 December 29

View File

@ -4,8 +4,9 @@
class API::PaymentSchedulesController < API::ApiController
before_action :authenticate_user!
before_action :set_payment_schedule, only: %i[download cancel]
before_action :set_payment_schedule_item, only: %i[cash_check refresh_item pay_item]
before_action :set_payment_schedule_item, only: %i[show_item cash_check refresh_item pay_item]
# retrieve all payment schedules for the current user, paginated
def index
@payment_schedules = PaymentSchedule.where('invoicing_profile_id = ?', current_user.invoicing_profile.id)
.includes(:invoicing_profile, :payment_schedule_items, :payment_schedule_objects)
@ -15,6 +16,7 @@ class API::PaymentSchedulesController < API::ApiController
.per(params[:size])
end
# retrieve all payment schedules for all users. Filtering is supported
def list
authorize PaymentSchedule
@ -62,6 +64,11 @@ class API::PaymentSchedulesController < API::ApiController
end
end
def show_item
authorize @payment_schedule_item.payment_schedule
render json: @payment_schedule_item, status: :ok
end
def cancel
authorize @payment_schedule

View File

@ -4,7 +4,7 @@ import {
CancelScheduleResponse,
CashCheckResponse, PayItemResponse,
PaymentSchedule,
PaymentScheduleIndexRequest, RefreshItemResponse
PaymentScheduleIndexRequest, PaymentScheduleItem, RefreshItemResponse
} from '../models/payment-schedule';
export default class PaymentScheduleAPI {
@ -23,6 +23,11 @@ export default class PaymentScheduleAPI {
return res?.data;
}
static async getItem (paymentScheduleItemId: number): Promise<PaymentScheduleItem> {
const res: AxiosResponse = await apiClient.get(`/api/payment_schedules/items/${paymentScheduleItemId}`);
return res?.data;
}
static async refreshItem (paymentScheduleItemId: number): Promise<RefreshItemResponse> {
const res: AxiosResponse = await apiClient.post(`/api/payment_schedules/items/${paymentScheduleItemId}/refresh_item`);
return res?.data;

View File

@ -11,6 +11,7 @@ import { User, UserRole } from '../../models/user';
import { PaymentSchedule, PaymentScheduleItem, PaymentScheduleItemState } from '../../models/payment-schedule';
import PaymentScheduleAPI from '../../api/payment-schedule';
import FormatLib from '../../lib/format';
import { StripeConfirmModal } from '../payment/stripe/stripe-confirm-modal';
interface PaymentSchedulesTableProps {
paymentSchedules: Array<PaymentSchedule>,
@ -412,14 +413,10 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
{t('app.shared.schedules_table.confirm_cancel_subscription')}
</FabModal>
<StripeElements>
<FabModal title={t('app.shared.schedules_table.resolve_action')}
isOpen={showResolveAction}
{tempDeadline && <StripeConfirmModal isOpen={showResolveAction}
toggleModal={toggleResolveActionModal}
onConfirm={afterAction}
confirmButton={t('app.shared.schedules_table.ok_button')}
preventConfirm={isConfirmActionDisabled}>
{tempDeadline && <StripeConfirm clientSecret={tempDeadline.client_secret} onResponse={toggleConfirmActionButton} />}
</FabModal>
onSuccess={afterAction}
paymentScheduleItemId={tempDeadline.id} />}
{tempSchedule && <UpdateCardModal isOpen={showUpdateCard}
toggleModal={toggleUpdateCardModal}
operator={operator}

View File

@ -0,0 +1,55 @@
import { StripeConfirm } from './stripe-confirm';
import { FabModal } from '../../base/fab-modal';
import React, { useEffect, useState } from 'react';
import PaymentScheduleAPI from '../../../api/payment-schedule';
import { PaymentScheduleItem } from '../../../models/payment-schedule';
import { useTranslation } from 'react-i18next';
interface StripeConfirmModalProps {
isOpen: boolean,
toggleModal: () => void,
onSuccess: () => void,
paymentScheduleItemId: number,
}
/**
* Modal dialog that trigger a 3D secure confirmation for the given payment schedule item (deadline for a payment schedule).
*/
export const StripeConfirmModal: React.FC<StripeConfirmModalProps> = ({ isOpen, toggleModal, onSuccess, paymentScheduleItemId }) => {
const { t } = useTranslation('shared');
const [item, setItem] = useState<PaymentScheduleItem>(null);
const [isPending, setIsPending] = useState(false);
useEffect(() => {
PaymentScheduleAPI.getItem(paymentScheduleItemId).then(data => {
setItem(data);
});
}, [paymentScheduleItemId]);
/**
* Callback triggered when the confirm button was clicked in the modal.
*/
const onConfirmed = (): void => {
togglePending();
onSuccess();
};
/**
* Enable/disable the confirm button of the "action" modal
*/
const togglePending = (): void => {
setIsPending(!isPending);
};
return (
<FabModal title={t('app.shared.schedules_table.resolve_action')}
isOpen={isOpen}
toggleModal={toggleModal}
onConfirm={onConfirmed}
confirmButton={t('app.shared.schedules_table.ok_button')}
preventConfirm={isPending}>
{item && <StripeConfirm clientSecret={item.client_secret} onResponse={togglePending} />}
</FabModal>
);
};

View File

@ -35,7 +35,7 @@ const EditPlanCategoryComponent: React.FC<EditPlanCategoryProps> = ({ onSuccess,
/**
* The edit has been confirmed by the user.
* Call the API to trigger the update of the temporary set plan-category
* Call the API to trigger the update of the temporary set plan-category.
*/
const onEditConfirmed = (): void => {
PlanCategoryAPI.update(tempCategory).then((updatedCategory) => {

View File

@ -14,9 +14,10 @@ class PaymentScheduleItem < Footprintable
def payment_intent
return unless payment_gateway_object
return unless payment_gateway_object.gateway_object.gateway == 'Stripe'
stp_invoice = payment_gateway_object.gateway_object.retrieve
Stripe::PaymentIntent.retrieve(stp_invoice.payment_intent, api_key: Setting.get('stripe_secret_key')) # FIXME, maybe this is only used for stripe?
Stripe::PaymentIntent.retrieve(stp_invoice.payment_intent, api_key: Setting.get('stripe_secret_key'))
end
def self.columns_out_of_footprint

View File

@ -8,7 +8,7 @@ class PaymentSchedulePolicy < ApplicationPolicy
end
end
%w[refresh_item? download? pay_item?].each do |action|
%w[refresh_item? download? pay_item? show_item?].each do |action|
define_method action do
user.admin? || user.manager? || (record.invoicing_profile.user_id == user.id)
end

View File

@ -24,7 +24,5 @@ if payment_schedule.gateway_subscription
end
end
json.items payment_schedule.payment_schedule_items do |item|
json.extract! item, :id, :due_date, :state, :invoice_id, :payment_method
json.amount item.amount / 100.00
json.client_secret item.payment_intent.client_secret if item.payment_gateway_object && item.state == 'requires_action'
json.partial! 'api/payment_schedules/payment_schedule_item', item: item
end

View File

@ -0,0 +1,4 @@
# frozen_string_literal: true
json.extract! item, :id, :due_date, :state, :invoice_id, :payment_method
json.amount item.amount / 100.00

View File

@ -0,0 +1,6 @@
# frozen_string_literal: true
json.partial! 'api/payment_schedules/payment_schedule_item', item: @payment_schedule_item
if @payment_schedule_item.payment_gateway_object && @payment_schedule_item.state == 'requires_action'
json.client_secret @payment_schedule_item.payment_intent.client_secret
end

View File

@ -123,6 +123,7 @@ Rails.application.routes.draw do
post 'list', action: 'list', on: :collection
put 'cancel', on: :member
get 'download', on: :member
get 'items/:id', action: 'show_item', on: :collection
post 'items/:id/cash_check', action: 'cash_check', on: :collection
post 'items/:id/refresh_item', action: 'refresh_item', on: :collection
post 'items/:id/pay_item', action: 'pay_item', on: :collection

View File

@ -29,5 +29,9 @@ class Payment::Item
false
end
def gateway
klass[/^(PayZen|Stripe)::/, 1]
end
def retrieve(_id = nil, *_args); end
end