mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-21 15:54:22 +01:00
(feat) When a payment schedule is in error or canceled, ability to re-enable it with another payment method
This commit is contained in:
parent
d8f27f0b1a
commit
634da414f8
@ -6,7 +6,7 @@
|
|||||||
- Ability to select "bank transfer" as the payment mean for a payment schedule
|
- Ability to select "bank transfer" as the payment mean for a payment schedule
|
||||||
- When a payment schedule was canceled by the payment gateway, alert the users
|
- When a payment schedule was canceled by the payment gateway, alert the users
|
||||||
- When a payment schedule is in error, alert the users
|
- When a payment schedule is in error, alert the users
|
||||||
- Specilized VAT rate cannot be defined unless the VAT is enabled and saved
|
- When a payment schedule is in error or canceled, ability to re-enable it with another payment method
|
||||||
- Fix card image ratio
|
- Fix card image ratio
|
||||||
- Update events heading style
|
- Update events heading style
|
||||||
- Update some icons
|
- Update some icons
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
# API Controller for resources of PaymentSchedule
|
# API Controller for resources of PaymentSchedule
|
||||||
class API::PaymentSchedulesController < API::ApiController
|
class API::PaymentSchedulesController < API::ApiController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
before_action :set_payment_schedule, only: %i[download cancel]
|
before_action :set_payment_schedule, only: %i[download cancel update]
|
||||||
before_action :set_payment_schedule_item, only: %i[show_item cash_check confirm_transfer refresh_item pay_item]
|
before_action :set_payment_schedule_item, only: %i[show_item cash_check confirm_transfer refresh_item pay_item]
|
||||||
|
|
||||||
# retrieve all payment schedules for the current user, paginated
|
# retrieve all payment schedules for the current user, paginated
|
||||||
@ -85,6 +85,17 @@ class API::PaymentSchedulesController < API::ApiController
|
|||||||
render json: { canceled_at: canceled_at }, status: :ok
|
render json: { canceled_at: canceled_at }, status: :ok
|
||||||
end
|
end
|
||||||
|
|
||||||
|
## Only the update of the payment method is allowed
|
||||||
|
def update
|
||||||
|
authorize PaymentSchedule
|
||||||
|
|
||||||
|
if PaymentScheduleService.new.update_payment_mean(@payment_schedule, update_params)
|
||||||
|
render :show, status: :ok, location: @payment_schedule
|
||||||
|
else
|
||||||
|
render json: @payment_schedule.errors, status: :unprocessable_entity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def set_payment_schedule
|
def set_payment_schedule
|
||||||
@ -94,4 +105,8 @@ class API::PaymentSchedulesController < API::ApiController
|
|||||||
def set_payment_schedule_item
|
def set_payment_schedule_item
|
||||||
@payment_schedule_item = PaymentScheduleItem.find(params[:id])
|
@payment_schedule_item = PaymentScheduleItem.find(params[:id])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_params
|
||||||
|
params.require(:payment_schedule).permit(:payment_method)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -47,4 +47,9 @@ export default class PaymentScheduleAPI {
|
|||||||
const res: AxiosResponse = await apiClient.put(`/api/payment_schedules/${paymentScheduleId}/cancel`);
|
const res: AxiosResponse = await apiClient.put(`/api/payment_schedules/${paymentScheduleId}/cancel`);
|
||||||
return res?.data;
|
return res?.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async update (paymentSchedule: PaymentSchedule): Promise<PaymentSchedule> {
|
||||||
|
const res:AxiosResponse<PaymentSchedule> = await apiClient.patch(`/api/payment_schedules/${paymentSchedule.id}`, paymentSchedule);
|
||||||
|
return res?.data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,13 @@ import { FabModal } from '../base/fab-modal';
|
|||||||
import FormatLib from '../../lib/format';
|
import FormatLib from '../../lib/format';
|
||||||
import { StripeConfirmModal } from '../payment/stripe/stripe-confirm-modal';
|
import { StripeConfirmModal } from '../payment/stripe/stripe-confirm-modal';
|
||||||
import { UpdateCardModal } from '../payment/update-card-modal';
|
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.
|
// we want to display some buttons only once. This is the types of buttons it applies to.
|
||||||
export enum TypeOnce {
|
export enum TypeOnce {
|
||||||
CardUpdate = 'card-update',
|
CardUpdate = 'card-update',
|
||||||
SubscriptionCancel = 'subscription-cancel',
|
SubscriptionCancel = 'subscription-cancel',
|
||||||
|
UpdatePaymentMean = 'update-payment-mean'
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PaymentScheduleItemActionsProps {
|
interface PaymentScheduleItemActionsProps {
|
||||||
@ -47,6 +49,8 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
|
|||||||
const [showResolveAction, setShowResolveAction] = useState<boolean>(false);
|
const [showResolveAction, setShowResolveAction] = useState<boolean>(false);
|
||||||
// is open, the modal dialog to update the card details
|
// is open, the modal dialog to update the card details
|
||||||
const [showUpdateCard, setShowUpdateCard] = useState<boolean>(false);
|
const [showUpdateCard, setShowUpdateCard] = useState<boolean>(false);
|
||||||
|
// is open, the modal dialog to update the payment mean
|
||||||
|
const [showUpdatePaymentMean, setShowUpdatePaymentMean] = useState<boolean>(false);
|
||||||
// the user cannot confirm the action modal (3D secure), unless he has resolved the pending action
|
// the user cannot confirm the action modal (3D secure), unless he has resolved the pending action
|
||||||
const [isConfirmActionDisabled, setConfirmActionDisabled] = useState<boolean>(true);
|
const [isConfirmActionDisabled, setConfirmActionDisabled] = useState<boolean>(true);
|
||||||
|
|
||||||
@ -130,6 +134,23 @@ 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);
|
||||||
|
if (isPrivileged() && (!displayOnceStatus || displayOnceStatus === paymentScheduleItem.id)) {
|
||||||
|
displayOnceMap.get(TypeOnce.UpdatePaymentMean).set(paymentSchedule.id, paymentScheduleItem.id);
|
||||||
|
return (
|
||||||
|
<FabButton key={`update-payment-mean-${paymentScheduleItem.id}`}
|
||||||
|
onClick={toggleUpdatePaymentMeanModal}
|
||||||
|
icon={<i className="fas fa-money-bill-alt" />}>
|
||||||
|
{t('app.shared.payment_schedule_item_actions.update_payment_mean')}
|
||||||
|
</FabButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a button to update the credit card associated with the payment schedule
|
* Return a button to update the credit card associated with the payment schedule
|
||||||
*/
|
*/
|
||||||
@ -166,14 +187,18 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
|
|||||||
/**
|
/**
|
||||||
* Return the actions button(s) for current paymentScheduleItem with state Error or GatewayCanceled
|
* Return the actions button(s) for current paymentScheduleItem with state Error or GatewayCanceled
|
||||||
*/
|
*/
|
||||||
const errorActions = (): ReactElement => {
|
const errorActions = (): ReactElement[] => {
|
||||||
// if the payment schedule is canceled/in error, the schedule is over, and we can't update the card
|
// 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(TypeOnce.CardUpdate).set(paymentSchedule.id, paymentScheduleItem.id);
|
||||||
|
|
||||||
|
const buttons = [];
|
||||||
if (isPrivileged()) {
|
if (isPrivileged()) {
|
||||||
return cancelSubscriptionButton();
|
buttons.push(cancelSubscriptionButton());
|
||||||
|
buttons.push(updatePaymentMeanButton());
|
||||||
} else {
|
} else {
|
||||||
return <span>{t('app.shared.payment_schedule_item_actions.please_ask_reception')}</span>;
|
buttons.push(<span>{t('app.shared.payment_schedule_item_actions.please_ask_reception')}</span>);
|
||||||
}
|
}
|
||||||
|
return buttons;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -232,6 +257,13 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
|
|||||||
setShowUpdateCard(!showUpdateCard);
|
setShowUpdateCard(!showUpdateCard);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show/hide the modal dialog to update the payment mean
|
||||||
|
*/
|
||||||
|
const toggleUpdatePaymentMeanModal = (): void => {
|
||||||
|
setShowUpdatePaymentMean(!showUpdatePaymentMean);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After the user has confirmed that he wants to cash the check, update the API, refresh the list and close the modal.
|
* After the user has confirmed that he wants to cash the check, update the API, refresh the list and close the modal.
|
||||||
*/
|
*/
|
||||||
@ -245,10 +277,10 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* After the user has confirmed that he validates the tranfer, update the API, refresh the list and close the modal.
|
* After the user has confirmed that he validates the transfer, update the API, refresh the list and close the modal.
|
||||||
*/
|
*/
|
||||||
const onTransferConfirmed = (): void => {
|
const onTransferConfirmed = (): void => {
|
||||||
PaymentScheduleAPI.confirmTransfer(paymentSchedule.id).then((res) => {
|
PaymentScheduleAPI.confirmTransfer(paymentScheduleItem.id).then((res) => {
|
||||||
if (res.state === PaymentScheduleItemState.Paid) {
|
if (res.state === PaymentScheduleItemState.Paid) {
|
||||||
onSuccess();
|
onSuccess();
|
||||||
toggleConfirmTransferModal();
|
toggleConfirmTransferModal();
|
||||||
@ -297,6 +329,14 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the update of the payment mean was successful, refresh the list and close the modal
|
||||||
|
*/
|
||||||
|
const onPaymentMeanUpdateSuccess = (): void => {
|
||||||
|
onSuccess();
|
||||||
|
toggleUpdatePaymentMeanModal();
|
||||||
|
};
|
||||||
|
|
||||||
if (!show) return null;
|
if (!show) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -359,6 +399,12 @@ export const PaymentScheduleItemActions: React.FC<PaymentScheduleItemActionsProp
|
|||||||
onError={onError}
|
onError={onError}
|
||||||
schedule={paymentSchedule}>
|
schedule={paymentSchedule}>
|
||||||
</UpdateCardModal>
|
</UpdateCardModal>
|
||||||
|
{/* Update the payment mean */}
|
||||||
|
<UpdatePaymentMeanModal isOpen={showUpdatePaymentMean}
|
||||||
|
toggleModal={toggleUpdatePaymentMeanModal}
|
||||||
|
onError={onError}
|
||||||
|
afterSuccess={onPaymentMeanUpdateSuccess}
|
||||||
|
paymentSchedule={paymentSchedule} />
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
@ -32,7 +32,8 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
|
|||||||
// we want to display some buttons only once. This map keep track of the buttons that have been displayed.
|
// 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([
|
const [displayOnceMap] = useState<Map<TypeOnce, Map<number, number>>>(new Map([
|
||||||
[TypeOnce.SubscriptionCancel, new Map()],
|
[TypeOnce.SubscriptionCancel, new Map()],
|
||||||
[TypeOnce.CardUpdate, new Map()]
|
[TypeOnce.CardUpdate, new Map()],
|
||||||
|
[TypeOnce.UpdatePaymentMean, new Map()]
|
||||||
]));
|
]));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Select from 'react-select';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { FabModal } from '../base/fab-modal';
|
||||||
|
import { PaymentMethod, PaymentSchedule } from '../../models/payment-schedule';
|
||||||
|
import PaymentScheduleAPI from '../../api/payment-schedule';
|
||||||
|
|
||||||
|
interface UpdatePaymentMeanModalProps {
|
||||||
|
isOpen: boolean,
|
||||||
|
toggleModal: () => void,
|
||||||
|
onError: (message: string) => void,
|
||||||
|
afterSuccess: () => void,
|
||||||
|
paymentSchedule: PaymentSchedule
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Option format, expected by react-select
|
||||||
|
* @see https://github.com/JedWatson/react-select
|
||||||
|
*/
|
||||||
|
type selectOption = { value: PaymentMethod, label: string };
|
||||||
|
|
||||||
|
export const UpdatePaymentMeanModal: React.FC<UpdatePaymentMeanModalProps> = ({ isOpen, toggleModal, onError, afterSuccess, paymentSchedule }) => {
|
||||||
|
const { t } = useTranslation('admin');
|
||||||
|
|
||||||
|
const [paymentMean, setPaymentMean] = React.useState<PaymentMethod>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert all payment means to the react-select format
|
||||||
|
*/
|
||||||
|
const buildOptions = (): Array<selectOption> => {
|
||||||
|
return Object.keys(PaymentMethod).filter(pm => PaymentMethod[pm] !== PaymentMethod.Card).map(pm => {
|
||||||
|
return { value: PaymentMethod[pm], label: t(`app.admin.update_payment_mean_modal.method_${pm}`) };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the payment mean is changed in the select, update the state
|
||||||
|
*/
|
||||||
|
const handleMeanSelected = (option: selectOption): void => {
|
||||||
|
setPaymentMean(option.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the user clicks on the update button, update the default payment mean for the given payment schedule
|
||||||
|
*/
|
||||||
|
const handlePaymentMeanUpdate = (): void => {
|
||||||
|
PaymentScheduleAPI.update({
|
||||||
|
id: paymentSchedule.id,
|
||||||
|
payment_method: paymentMean
|
||||||
|
}).then(() => {
|
||||||
|
afterSuccess();
|
||||||
|
}).catch(error => {
|
||||||
|
onError(error.message);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FabModal isOpen={isOpen}
|
||||||
|
className="update-payment-mean-modal"
|
||||||
|
title={t('app.admin.update_payment_mean_modal.title')}
|
||||||
|
confirmButton={t('app.admin.update_payment_mean_modal.confirm_button')}
|
||||||
|
onConfirm={handlePaymentMeanUpdate}
|
||||||
|
toggleModal={toggleModal}
|
||||||
|
closeButton={true}>
|
||||||
|
<span>{t('app.admin.update_payment_mean_modal.update_info')}</span>
|
||||||
|
<Select className="payment-mean-select"
|
||||||
|
placeholder={t('app.admin.update_payment_mean_modal.select_payment_mean')}
|
||||||
|
id="payment-mean"
|
||||||
|
onChange={handleMeanSelected}
|
||||||
|
options={buildOptions()}></Select>
|
||||||
|
</FabModal>
|
||||||
|
);
|
||||||
|
};
|
@ -476,8 +476,6 @@ Application.Controllers.controller('InvoicesController', ['$scope', '$state', 'I
|
|||||||
controller: ['$scope', '$uibModalInstance', 'rate', 'active', 'rateHistory', 'activeHistory', 'multiVAT', function ($scope, $uibModalInstance, rate, active, rateHistory, activeHistory, multiVAT) {
|
controller: ['$scope', '$uibModalInstance', 'rate', 'active', 'rateHistory', 'activeHistory', 'multiVAT', function ($scope, $uibModalInstance, rate, active, rateHistory, activeHistory, multiVAT) {
|
||||||
$scope.rate = rate;
|
$scope.rate = rate;
|
||||||
$scope.isSelected = active;
|
$scope.isSelected = active;
|
||||||
// this one is read only
|
|
||||||
$scope.isActive = active;
|
|
||||||
$scope.history = [];
|
$scope.history = [];
|
||||||
|
|
||||||
// callback on "enable VAT" switch toggle
|
// callback on "enable VAT" switch toggle
|
||||||
|
@ -25,28 +25,28 @@ export interface PaymentScheduleItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface PaymentSchedule {
|
export interface PaymentSchedule {
|
||||||
max_length: number;
|
max_length?: number;
|
||||||
id: number,
|
id: number,
|
||||||
total: number,
|
total?: number,
|
||||||
reference: string,
|
reference?: string,
|
||||||
payment_method: PaymentMethod,
|
payment_method: PaymentMethod,
|
||||||
items: Array<PaymentScheduleItem>,
|
items?: Array<PaymentScheduleItem>,
|
||||||
created_at: Date,
|
created_at?: Date,
|
||||||
chained_footprint: boolean,
|
chained_footprint?: boolean,
|
||||||
main_object: {
|
main_object?: {
|
||||||
type: string,
|
type: string,
|
||||||
id: number
|
id: number
|
||||||
},
|
},
|
||||||
user: {
|
user?: {
|
||||||
id: number,
|
id: number,
|
||||||
name: string
|
name: string
|
||||||
},
|
},
|
||||||
operator: {
|
operator?: {
|
||||||
id: number,
|
id: number,
|
||||||
first_name: string,
|
first_name: string,
|
||||||
last_name: string,
|
last_name: string,
|
||||||
},
|
},
|
||||||
gateway: 'PayZen' | 'Stripe',
|
gateway?: 'PayZen' | 'Stripe',
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PaymentScheduleIndexRequest {
|
export interface PaymentScheduleIndexRequest {
|
||||||
|
@ -51,7 +51,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class="btn btn-warning pull-left" ng-click="editMultiVAT()" ng-show="isActive" translate>{{ 'app.admin.invoices.edit_multi_VAT_button' }}</button>
|
<button class="btn btn-warning pull-left" ng-click="editMultiVAT()" ng-show="isSelected" translate>{{ 'app.admin.invoices.edit_multi_VAT_button' }}</button>
|
||||||
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
<button class="btn btn-warning" ng-click="ok()" translate>{{ 'app.shared.buttons.confirm' }}</button>
|
||||||
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
<button class="btn btn-default" ng-click="cancel()" translate>{{ 'app.shared.buttons.cancel' }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Check the access policies for API::PaymentSchedulesController
|
# Check the access policies for API::PaymentSchedulesController
|
||||||
class PaymentSchedulePolicy < ApplicationPolicy
|
class PaymentSchedulePolicy < ApplicationPolicy
|
||||||
%w[list? cash_check? confirm_transfer? cancel?].each do |action|
|
%w[list? cash_check? confirm_transfer? cancel? update?].each do |action|
|
||||||
define_method action do
|
define_method action do
|
||||||
user.admin? || user.manager?
|
user.admin? || user.manager?
|
||||||
end
|
end
|
||||||
|
@ -157,6 +157,10 @@ class PaymentScheduleService
|
|||||||
ps
|
ps
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Cancel the given PaymentSchedule: cancel the remote subscription on the payment gateway, mark the PaymentSchedule as cancelled,
|
||||||
|
# the remaining PaymentScheduleItems as canceled too, and cancel the associated Subscription.
|
||||||
|
##
|
||||||
def self.cancel(payment_schedule)
|
def self.cancel(payment_schedule)
|
||||||
PaymentGatewayService.new.cancel_subscription(payment_schedule)
|
PaymentGatewayService.new.cancel_subscription(payment_schedule)
|
||||||
|
|
||||||
@ -173,8 +177,26 @@ class PaymentScheduleService
|
|||||||
subscription.canceled_at
|
subscription.canceled_at
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Update the payment mean associated with the given PaymentSchedule and reset the erroneous items
|
||||||
|
##
|
||||||
|
def update_payment_mean(payment_schedule, payment_mean)
|
||||||
|
payment_schedule.update(payment_mean) && reset_erroneous_payment_schedule_items(payment_schedule)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
##
|
||||||
|
# After the payment method has been updated, we need to reset the erroneous payment schedule items
|
||||||
|
# so the admin can confirm them to generate the invoice
|
||||||
|
##
|
||||||
|
def reset_erroneous_payment_schedule_items(payment_schedule)
|
||||||
|
results = payment_schedule.payment_schedule_items.where(state: %w[error gateway_canceled]).map do |item|
|
||||||
|
item.update_attributes(state: item.due_date < DateTime.current ? 'pending' : 'new')
|
||||||
|
end
|
||||||
|
results.reduce(true) { |acc, item| acc && item }
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# The first PaymentScheduleItem contains references to the reservation price (if any) and to the adjustment price
|
# The first PaymentScheduleItem contains references to the reservation price (if any) and to the adjustment price
|
||||||
# for the subscription (if any) and the wallet transaction (if any)
|
# for the subscription (if any) and the wallet transaction (if any)
|
||||||
|
@ -19,7 +19,7 @@ json.main_object do
|
|||||||
end
|
end
|
||||||
if payment_schedule.gateway_subscription
|
if payment_schedule.gateway_subscription
|
||||||
# this attribute is used to known which gateway should we interact with, in the front-end
|
# this attribute is used to known which gateway should we interact with, in the front-end
|
||||||
json.gateway json.classname payment_schedule.gateway_subscription.gateway
|
json.gateway payment_schedule.gateway_subscription.gateway
|
||||||
end
|
end
|
||||||
json.items payment_schedule.payment_schedule_items do |item|
|
json.items payment_schedule.payment_schedule_items do |item|
|
||||||
json.partial! 'api/payment_schedules/payment_schedule_item', item: item
|
json.partial! 'api/payment_schedules/payment_schedule_item', item: item
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
json.partial! 'api/payment_schedules/payment_schedule', payment_schedule: @payment_schedule_item.payment_schedule
|
json.partial! 'api/payment_schedules/payment_schedule', payment_schedule: @payment_schedule
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
json.setting do
|
json.setting do
|
||||||
json.partial! 'api/settings/setting', setting: @setting
|
json.partial! 'api/settings/setting', setting: @setting
|
||||||
if @show_history
|
if @show_history
|
||||||
json.history @setting.history_values do |value|
|
json.history @setting.history_values.includes(:invoicing_profile) do |value|
|
||||||
json.extract! value, :id, :value, :created_at
|
json.extract! value, :id, :value, :created_at
|
||||||
unless value.invoicing_profile.nil?
|
unless value.invoicing_profile.nil?
|
||||||
json.user do
|
json.user do
|
||||||
|
@ -762,6 +762,13 @@ en:
|
|||||||
reference: "Reference"
|
reference: "Reference"
|
||||||
customer: "Customer"
|
customer: "Customer"
|
||||||
date: "Date"
|
date: "Date"
|
||||||
|
update_payment_mean_modal:
|
||||||
|
title: "Update the payment mean"
|
||||||
|
update_info: "Please specify below the new payment mean for this payment schedule to continue."
|
||||||
|
select_payment_mean: "Select a new payment mean"
|
||||||
|
method_Transfer: "By bank transfer"
|
||||||
|
method_Check: "By check"
|
||||||
|
confirm_button: "Update"
|
||||||
#management of users, labels, groups, and so on
|
#management of users, labels, groups, and so on
|
||||||
members:
|
members:
|
||||||
users_management: "Users management"
|
users_management: "Users management"
|
||||||
|
@ -505,6 +505,7 @@ en:
|
|||||||
confirm_check: "Confirm cashing"
|
confirm_check: "Confirm cashing"
|
||||||
resolve_action: "Resolve the action"
|
resolve_action: "Resolve the action"
|
||||||
update_card: "Update the card"
|
update_card: "Update the card"
|
||||||
|
update_payment_mean: "Update the payment mean"
|
||||||
please_ask_reception: "For any questions, please contact the FabLab's reception."
|
please_ask_reception: "For any questions, please contact the FabLab's reception."
|
||||||
confirm_button: "Confirm"
|
confirm_button: "Confirm"
|
||||||
confirm_check_cashing: "Confirm the cashing of the check"
|
confirm_check_cashing: "Confirm the cashing of the check"
|
||||||
|
@ -376,9 +376,9 @@ en:
|
|||||||
notify_member_payment_schedule_failed:
|
notify_member_payment_schedule_failed:
|
||||||
schedule_failed: "Failed card debit for the %{DATE} deadline, for your schedule %{REFERENCE}"
|
schedule_failed: "Failed card debit for the %{DATE} deadline, for your schedule %{REFERENCE}"
|
||||||
notify_admin_payment_schedule_gateway_canceled:
|
notify_admin_payment_schedule_gateway_canceled:
|
||||||
schedule_error: "The payment schedule %{REFERENCE} was canceled by the gateway. An action is required."
|
schedule_canceled: "The payment schedule %{REFERENCE} was canceled by the gateway. An action is required."
|
||||||
notify_member_payment_schedule_gateway_canceled:
|
notify_member_payment_schedule_gateway_canceled:
|
||||||
schedule_error: "Your payment schedule %{REFERENCE} was canceled by the gateway."
|
schedule_canceled: "Your payment schedule %{REFERENCE} was canceled by the gateway."
|
||||||
notify_admin_payment_schedule_check_deadline:
|
notify_admin_payment_schedule_check_deadline:
|
||||||
schedule_deadline: "You must cash the check for the %{DATE} deadline, for schedule %{REFERENCE}"
|
schedule_deadline: "You must cash the check for the %{DATE} deadline, for schedule %{REFERENCE}"
|
||||||
notify_admin_payment_schedule_transfer_deadline:
|
notify_admin_payment_schedule_transfer_deadline:
|
||||||
|
@ -119,7 +119,7 @@ Rails.application.routes.draw do
|
|||||||
get 'first', action: 'first', on: :collection
|
get 'first', action: 'first', on: :collection
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :payment_schedules, only: %i[index show] do
|
resources :payment_schedules, only: %i[index show update] do
|
||||||
post 'list', action: 'list', on: :collection
|
post 'list', action: 'list', on: :collection
|
||||||
put 'cancel', on: :member
|
put 'cancel', on: :member
|
||||||
get 'download', on: :member
|
get 'download', on: :member
|
||||||
|
Loading…
x
Reference in New Issue
Block a user