1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-18 07:52:23 +01:00

(bug) members cannot update their cards for payment schedules

This commit is contained in:
Sylvain 2023-02-17 16:07:18 +01:00
parent 8740c4971d
commit 7f53abfbf9
4 changed files with 27 additions and 43 deletions

View File

@ -14,6 +14,7 @@
- Fix a bug: event image updates are not reflected unless the browser's cache is purged
- Fix a bug: schedules jobs are not launched at the right time
- Fix a bug: unable to update the title of a training
- Fix a bug: members cannot update their cards for payment schedules
- [TODO DEPLOY] `rails fablab:fix_availabilities` THEN `rails fablab:setup:build_places_cache`
- [TODO DEPLOY] `\curl -sSL https://raw.githubusercontent.com/sleede/fab-manager/master/scripts/rename-supporting-document.sh | bash`

View File

@ -1,8 +1,7 @@
import {
PaymentMethod,
PaymentSchedule,
PaymentScheduleItem,
PaymentScheduleItemState
PaymentScheduleItem
} from '../../models/payment-schedule';
import { ReactElement, useState } from 'react';
import * as React from 'react';
@ -17,11 +16,7 @@ import { UpdateCardModal } from '../payment/update-card-modal';
import { UpdatePaymentMeanModal } from './update-payment-mean-modal';
// we want to display some buttons only once. This is the types of buttons it applies to.
export enum TypeOnce {
CardUpdate = 'card-update',
SubscriptionCancel = 'subscription-cancel',
UpdatePaymentMean = 'update-payment-mean'
}
export type TypeOnce = 'card-update'|'subscription-cancel'|'update-payment-mean';
interface PaymentScheduleItemActionsProps {
paymentScheduleItem: PaymentScheduleItem,
@ -79,9 +74,9 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
* Return a button to cancel the given subscription, if the user is privileged enough
*/
const cancelSubscriptionButton = (): ReactElement => {
const displayOnceStatus = displayOnceMap.get(TypeOnce.SubscriptionCancel).get(paymentSchedule.id);
const displayOnceStatus = displayOnceMap.get('subscription-cancel').get(paymentSchedule.id);
if (isPrivileged() && (!displayOnceStatus || displayOnceStatus === paymentScheduleItem.id)) {
displayOnceMap.get(TypeOnce.SubscriptionCancel).set(paymentSchedule.id, paymentScheduleItem.id);
displayOnceMap.get('subscription-cancel').set(paymentSchedule.id, paymentScheduleItem.id);
return (
<FabButton key={`cancel-subscription-${paymentSchedule.id}`}
onClick={toggleCancelSubscriptionModal}
@ -139,9 +134,9 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
* Return a button to update the default payment mean for the current payment schedule
*/
const updatePaymentMeanButton = (): ReactElement => {
const displayOnceStatus = displayOnceMap.get(TypeOnce.UpdatePaymentMean).get(paymentSchedule.id);
const displayOnceStatus = displayOnceMap.get('update-payment-mean').get(paymentSchedule.id);
if (isPrivileged() && (!displayOnceStatus || displayOnceStatus === paymentScheduleItem.id)) {
displayOnceMap.get(TypeOnce.UpdatePaymentMean).set(paymentSchedule.id, paymentScheduleItem.id);
displayOnceMap.get('update-payment-mean').set(paymentSchedule.id, paymentScheduleItem.id);
return (
<FabButton key={`update-payment-mean-${paymentScheduleItem.id}`}
onClick={toggleUpdatePaymentMeanModal}
@ -156,9 +151,9 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
* Return a button to update the credit card associated with the payment schedule
*/
const updateCardButton = (): ReactElement => {
const displayOnceStatus = displayOnceMap.get(TypeOnce.SubscriptionCancel).get(paymentSchedule.id);
if (isPrivileged() && (!displayOnceStatus || displayOnceStatus === paymentScheduleItem.id)) {
displayOnceMap.get(TypeOnce.CardUpdate).set(paymentSchedule.id, paymentScheduleItem.id);
const displayOnceStatus = displayOnceMap.get('card-update').get(paymentSchedule.id);
if (!displayOnceStatus || displayOnceStatus === paymentScheduleItem.id) {
displayOnceMap.get('card-update').set(paymentSchedule.id, paymentScheduleItem.id);
return (
<FabButton key={`update-card-${paymentSchedule.id}`}
onClick={toggleUpdateCardModal}
@ -190,7 +185,7 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
*/
const errorActions = (): ReactElement[] => {
// if the payment schedule is canceled/in error, the schedule is over, and we can't update the card
displayOnceMap.get(TypeOnce.CardUpdate).set(paymentSchedule.id, paymentScheduleItem.id);
displayOnceMap.get('card-update').set(paymentSchedule.id, paymentScheduleItem.id);
const buttons = [];
if (isPrivileged()) {
@ -270,7 +265,7 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
*/
const onCheckCashingConfirmed = (): void => {
PaymentScheduleAPI.cashCheck(paymentScheduleItem.id).then((res) => {
if (res.state === PaymentScheduleItemState.Paid) {
if (res.state === 'paid') {
onSuccess();
toggleConfirmCashingModal();
}
@ -282,7 +277,7 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
*/
const onTransferConfirmed = (): void => {
PaymentScheduleAPI.confirmTransfer(paymentScheduleItem.id).then((res) => {
if (res.state === PaymentScheduleItemState.Paid) {
if (res.state === 'paid') {
onSuccess();
toggleConfirmTransferModal();
}
@ -293,7 +288,7 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
* When the card was successfully updated, pay the invoice (using the new payment method) and close the modal
*/
const handleCardUpdateSuccess = (): void => {
if (paymentScheduleItem.state === PaymentScheduleItemState.RequirePaymentMethod) {
if (paymentScheduleItem.state === 'requires_payment_method') {
PaymentScheduleAPI.payItem(paymentScheduleItem.id).then(() => {
onSuccess();
onCardUpdateSuccess();
@ -342,13 +337,13 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
return (
<span className="payment-schedule-item-actions">
{paymentScheduleItem.state === PaymentScheduleItemState.Paid && downloadInvoiceButton(paymentScheduleItem.invoice_id)}
{paymentScheduleItem.state === PaymentScheduleItemState.Pending && pendingActions()}
{paymentScheduleItem.state === PaymentScheduleItemState.RequireAction && solveActionButton()}
{paymentScheduleItem.state === PaymentScheduleItemState.RequirePaymentMethod && updateCardButton()}
{paymentScheduleItem.state === PaymentScheduleItemState.Error && errorActions()}
{paymentScheduleItem.state === PaymentScheduleItemState.GatewayCanceled && errorActions()}
{paymentScheduleItem.state === PaymentScheduleItemState.New && newActions()}
{paymentScheduleItem.state === 'paid' && downloadInvoiceButton(paymentScheduleItem.invoice_id)}
{paymentScheduleItem.state === 'pending' && pendingActions()}
{paymentScheduleItem.state === 'requires_action' && solveActionButton()}
{paymentScheduleItem.state === 'requires_payment_method' && updateCardButton()}
{paymentScheduleItem.state === 'error' && errorActions()}
{paymentScheduleItem.state === 'gateway_canceled' && errorActions()}
{paymentScheduleItem.state === 'new' && newActions()}
<div className="modals">
{/* Confirm the cashing of the current deadline by check */}
<FabModal title={t('app.shared.payment_schedule_item_actions.confirm_check_cashing')}

View File

@ -4,11 +4,7 @@ import { useTranslation } from 'react-i18next';
import { Loader } from '../base/loader';
import _ from 'lodash';
import { User } from '../../models/user';
import {
PaymentSchedule,
PaymentScheduleItem,
PaymentScheduleItemState
} from '../../models/payment-schedule';
import type { PaymentSchedule, PaymentScheduleItem } from '../../models/payment-schedule';
import FormatLib from '../../lib/format';
import { PaymentScheduleItemActions, TypeOnce } from './payment-schedule-item-actions';
import { StripeElements } from '../payment/stripe/stripe-elements';
@ -34,9 +30,9 @@ const PaymentSchedulesTable: React.FC<PaymentSchedulesTableProps> = ({ paymentSc
const [showExpanded, setShowExpanded] = useState<Map<number, boolean>>(new Map());
// we want to display some buttons only once. This map keep track of the buttons that have been displayed.
const [displayOnceMap] = useState<Map<TypeOnce, Map<number, number>>>(new Map([
[TypeOnce.SubscriptionCancel, new Map()],
[TypeOnce.CardUpdate, new Map()],
[TypeOnce.UpdatePaymentMean, new Map()]
['subscription-cancel', new Map()],
['card-update', new Map()],
['update-payment-mean', new Map()]
]));
const [gateway, setGateway] = useState<Setting>(null);
@ -109,7 +105,7 @@ const PaymentSchedulesTable: React.FC<PaymentSchedulesTableProps> = ({ paymentSc
*/
const formatState = (item: PaymentScheduleItem, schedule: PaymentSchedule): JSX.Element => {
let res = t(`app.shared.payment_schedules_table.state_${item.state}${item.state === 'pending' ? '_' + schedule.payment_method : ''}`);
if (item.state === PaymentScheduleItemState.Paid) {
if (item.state === 'paid') {
const key = `app.shared.payment_schedules_table.method_${item.payment_method}`;
res += ` (${t(key)})`;
}

View File

@ -1,14 +1,6 @@
import { TDateISO, TDateISODate } from '../typings/date-iso';
export enum PaymentScheduleItemState {
New = 'new',
Pending = 'pending',
RequirePaymentMethod = 'requires_payment_method',
RequireAction = 'requires_action',
Paid = 'paid',
Error = 'error',
GatewayCanceled = 'gateway_canceled'
}
export type PaymentScheduleItemState = 'new'|'pending'|'requires_payment_method'|'requires_action'|'paid'|'error'|'gateway_canceled';
export enum PaymentMethod {
Card = 'card',