Development
Feature Flags
Feature Flag | Description |
---|
enable-ticket-restaurant-credit-card-paycomet | This flag will be responsible for activating ticket restaurant payment method using the online payment |
enable-ticket-restaurant-voucher-paycomet | This flag will be responsible for activating ticket restaurant payment method using the voucher in person |
Code Changes
PaymentMethodBrand
The essential part of this feature is the addition of new values for ticket restaurant to the paymentMethodBrand property, which will be responsible for identifying the payment method made and passing it on to all systems listed below, since the system used behind the scenes is payment via credit card.
ENUM | VALUE |
---|
TICKET_RESTAURANT | TICKET_RESTAURANT |
TICKET_RESTAURANT_VOUCHER | TICKET_RESTAURANT_VOUCHER |
Frontend
Development
payment-method/index.tsx
const SelectedTicketRestaurantOptionItem = (
<PaymentMethodAddNewItemOption
text={formatMessage({ id: ticketRestaurantLabel(isGuestOrder) })}
Icon={styledCardIcon(PaymentMethodBrandType.TICKET_RESTAURANT)}
onClick={getSelectedMethodClickHandler()}
selected
/>
);
payment-method/styled.tsx
import IconSodexo from 'components/icons/sodexo';
....
export const paymentsMethodIcon: Record<string, IconSVGElement> = {
[PaymentMethodBrandType.SODEXO]: IconSodexo,
[PaymentMethodBrandType.CHEQUE_GOURMET]: IconChequeGourmet,
[PaymentMethodBrandType.TICKET_RESTAURANT]: IconTicketRestaurant,
};
payment-method/types.ts
export enum PaymentMethodBrandType {
SODEXO = 'SODEXO',
SODEXO_VOUCHER = 'SODEXO_VOUCHER',
TICKET_RESTAURANT = 'TICKET_RESTAURANT',
TICKET_RESTAURANT_VOUCHER = 'TICKET_RESTAURANT_VOUCHER',
}
payment-method-options/payment-method-options.tsx
{method?.ticket_restaurant && method?.transient && (
<StyledOption>
<PaymentMethodOptionItemDivider />
<PaymentMethodAddNewItemOption
data-testid="add-ticket-restaurant-card-payment"
text={formatMessage({ id: ticketRestaurantLabel(isGuestOrder) })}
Icon={styledCardIcon(PaymentMethodBrandType.TICKET_RESTAURANT)}
onClick={e => handleTicketRestaurantOptionClick(e, 'card')}
isLoading={isLoadingPopup}
/>
</StyledOption>
)}
payment-method/utils/sort-payment-methods.ts
case 'TICKET_RESTAURANT':
return paymentMethods.filter(
p => p?.transient && p?.sodexo && p.accountIdentifier === typeOrder
);
case 'TICKET_RESTAURANT_VOUCHER':
return paymentMethods.filter(
p => p?.transient && p?.sodexo && p.accountIdentifier === typeOrder
);
const paymentMethodListTypeOrder = [
TICKET_RESTAURANT,
TICKET_RESTAURANT_VOUCHER,
]
payment-method-option/ticket-restaurant-method.tsx
import React from 'react';
import { useIntl } from 'react-intl';
import { MethodType } from './styled';
const TicketRestaurantMethod = () => {
const { formatMessage } = useIntl();
return <MethodType>{formatMessage({ id: 'payWithTicketRestaurantVoucher' })}</MethodType>;
};
export default SodexoMethod;
payment-method-option/index.tsx
import TicketRestaurantMethod from './ticket-restaurant-method';
if (method.ticketRestaurant) {
return <TicketRestaurantMethod />;
}
{method.ticketRestaurant && styledCardIcon(PaymentMethodBrandType.TICKET_RESTAURANT)}
payment/order-payment/use-order-payment.ts
Improve the paymentMethodBrandValue to add the Ticket Restaurant
if (isPaycometSodexoMethodSelected || isPaycometChequeGourmetMethodSelected) {
paymentMethodBrandValue = isPaycometSodexoMethodSelected
? PaymentMethodBrand.SODEXO
: PaymentMethodBrand.CHEQUE_GOURMET;
}
if (payment.isFreeOrderPayment) {
paymentAccount = {
ticketRestaurant: null,
};
}
const isPaymentWithTicketRestaurantVoucher =
selectedPaymentMethod?.ticketRestaurat &&
selectedPaymentMethod?.paymentMethodBrand === 'TICKET_RESTAURANT_VOUCHER';
const handleOrderCommit = useCallback(async () => {
...
},
[
...,
selectedPaymentMethod?.ticketRestaurant
]
paycomet-hosted-page-payment/paycomet-hosted-page-payment.tsx
Improve the paymentMethodBrandValue to add the Ticket Restaurant
if (isPaycometSodexoMethodSelected || isPaycometChequeGourmetMethodSelected) {
paymentMethodBrand = isPaycometSodexoMethodSelected
? PaymentMethodBrand.SODEXO
: PaymentMethodBrand.CHEQUE_GOURMET;
}
src/state/payment/constants.ts
Update all METHOD_PLACEHOLDER
to include ticket_restaurant
with null value
export const XXXX_METHOD_PLACEHOLDER: IPaymentMethod = {
...
ticketRestaurant: null,
};
Create a new METHOD_PLACEHOLDER
for ticket_restaurant
and ticket_restaurant_voucher
export const TICKET_RESTAURANT_METHOD_PLACEHOLDER: IPaymentMethod = {
...
ticketRestaurant: true,
};
export const TICKET_RESTAURANT_VOUCHER_METHOD_PLACEHOLDER: IPaymentMethod = {
...
ticketRestaurant: true,
fdAccountId: 'CASH',
accountIdentifier: 'TICKET_RESTAURANT',
paymentMethodBrand: 'TICKET_RESTAURANT',
};
state/payment/types.ts
export enum PaymentMethodBrand {
TICKET_RESTAURANT = 'TICKET_RESTAURANT',
TICKET_RESTAURANT_VOUCHER = 'TICKET_RESTAURANT_VOUCHER',
}
export interface IPaymentMethod {
ticketRestaurant?: boolean | null;
}
state/payment/hooks/use-payment.tsx
const cashAccount: IPaymentMethod = {
ticketRestaurant: null,
};
state/translations/en.json
{
...,
"addNewPaymentSodexo": "Pay with Ticket Restaurant",
"payWithPaymentSodexo": "Pay with Ticket Restaurant",
"payWithSodexoVoucher": "Pay with Ticket Restaurant Voucher",
}
utils/launchdarkly/flags.ts
/**
* Flag for enable ticket restaurant credit card in processor paycomet
*/
ENABLE_TICKET_CREDIT_CARD_PAYCOMET = 'enable-ticket-restaurant-credit-card-paycomet',
/**
* Flag for enable ticket restaurant voucher in processor paycomet
*/
ENABLE_TICKET_RESTAURANT_VOUCHER_PAYCOMET = 'enable-ticket-restaurant-voucher-paycomet',
utils/payment/voucher.ts
export const isVoucher = (method: IPaymentMethod) => {
return !!method.sodexo || !!method.chequeGourmet || !!method.ticketRestaurant;
};
Unit Tests
state/payment/__tests__/use-payment.test.tsx
jest.mock('state/launchdarkly', () => ({
useFlag: jest.fn(),
useGatewayFlags: jest.fn().mockReturnValue(''),
LaunchDarklyFlag: {
ENABLE_TICKET_RESTAURANT_VOUCHER_PAYCOMET: 'ticket-restaurant-string',
}));
utils/payment/__tests__/payment-method.test.ts
describe('isRemovablePaymentMethod', () => {
describe.each([
[{ ticketRestaurant: true }, false],
])("on '%s'", (input, expected) => {
it(`returns '${expected}'`, () => {
expect(isRemovablePaymentMethod(input as IPaymentMethod)).toEqual(expected);
});
});
});
Graphql
graphql/schemas/payments.gql
Add the PaymentMethodBrand
enum PaymentMethodBrand {
...
TICKET_RESTAURANT
TICKET_RESTAURANT_VOUCHER
}
https://github.com/rbilabs/intl-whitelabel-graphql/pull/952
Fulfillment
src/graphql.ts
export enum PaymentMethodBrand {
...,
TICKET_RESTAURANT = "TICKET_RESTAURANT",
TICKET_RESTAURANT_VOUCHER = "TICKET_RESTAURANT_VOUCHER",
}
legacy/schemas/payments.graphql
enum PaymentMethodBrand {
...
TICKET_RESTAURANT
TICKET_RESTAURANT_VOUCHER
}
https://github.com/rbilabs/intl-fulfillment-service/pull/813
Packages
orders/src/types/cart.ts
export enum PaymentMethodBrand {
...,
TICKET_RESTAURANT = 'TICKET_RESTAURANT',
TICKET_RESTAURANT_VOUCHER = 'TICKET_RESTAURANT_VOUCHER',
}
https://github.com/rbilabs/intl-packages/pull/1187
DMP
@tests/unit/pages/CashFlow/controllers/delegate.spec.ts
const expected = [
'TICKET_RESTAURANT',
'TICKET_RESTAURANT_VOUCHER',
];
src/constants/paymentMethod.ts
export enum PaymentMethod {
TICKET_RESTAURANT = 'TICKET_RESTAURANT',
TICKET_RESTAURANT_VOUCHER = 'TICKET_RESTAURANT_VOUCHER',
}
export const paymentMethodTranslation: Record<PaymentMethod, string> = {
TICKET_RESTAURANT: 'constants.paymentMethod.ticketRestaurant',
TICKET_RESTAURANT_VOUCHER: 'constants.paymentMethod.ticketRestaurantVoucher',
};
https://github.com/rbilabs/intl-expeditor-tablet/pull/742
DOP
delivery/settings/last-mile-settings-card/LastMileSettingsCard.tsx
export const paymentMethodTranslation: Record<PaymentMethod, keyof LocalizedDictionary> = {
TICKET_RESTAURANT: `${baseTranslationPath}.ticketRestaurant`,
TICKET_RESTAURANT_VOUCHER: `${baseTranslationPath}.ticketRestaurantVoucher`,
};
export enum PaymentMethod {
TICKET_RESTAURANT = 'TICKET_RESTAURANT',
TICKET_RESTAURANT_VOUCHER = 'TICKET_RESTAURANT_VOUCHER',
}
utils/orders.ts
export const paymentMethodTranslation: Record<string, string> = {
TICKET_RESTAURANT: 'delivery-mgmt.restaurantManagement.changeDriver.paidWith.ticketRestaurant',
TICKET_RESTAURANT_VOUCHER: 'delivery-mgmt.restaurantManagement.changeDriver.paidWith.ticketRestaurantVoucher',
};
https://github.com/rbilabs/ctg-fz-portal/pull/2799
Admin App
order-details/__tests__/order-details.spec.tsx
describe('Payment method', () => {
it.each`
case | paymentData | result
${'Ticket restaurant'} | ${{ cardType: 'VISA', paymentMethodBrand: 'TICKET_RESTAURANT' }} | ${'Ticket Restaurant'}
${'Ticket restaurant voucher'} | ${{ cardType: 'CASH', paymentMethodBrand: 'TICKET_RESTAURANT_VOUCHER' }} | ${'Ticket Restaurant Voucher'}
`('Should display $case payments accordingly', ({ paymentData, result }) => {
....
}
utils/utils.ts
export function paymentMethodBrandTranslationMap(paymentMethodBrand: string) {
const translatePaymentMethodBrand = {
TICKET_RESTAURANT: 'orderDetails.paymentMethodBrand.ticket_restaurant',
TICKET_RESTAURANT_VOUCHER: 'orderDetails.paymentMethodBrand.ticket_restaurant_voucher',
};
https://github.com/rbilabs/intl-admin-app/pull/403
Driver-app ( Voucher )
enums/index.ts
export enum PaymentMethod {
TICKET_RESTAURANT = 'TICKET_RESTAURANT',
TICKET_RESTAURANT_VOUCHER = 'TICKET_RESTAURANT_VOUCHER',
}
services/format.ts
export const paymentMethodTranslation: Record<PaymentMethod, string> = {
TICKET_RESTAURANT: `${pathPaymentMethosTranslation}.ticketRestaurant`,
TICKET_RESTAURANT_VOUCHER: `${pathPaymentMethosTranslation}.ticketRestaurantVoucher`,
};
https://github.com/rbilabs/intl-driver-app/pull/286
Tests
Ticket Restaurant Card
To make payments with the Ticket Restaurant card, we can use the same cards used for credit card payments. This integration with meal voucher cards is activated at restaurant points, together with Paycomet. We just need to validate that the credit card field is displayed to the user and that they can follow the same credit card payment flow and the paymentMethodBrand is filled with “TICKET_RESTAURANT”.
Ticket Restaurant Voucher
To make payments with the Ticket Restaurante Voucher, it is necessary to ensure that the process follows the CASH flow and the paymentMethodBrand is filled with “TICKET_RESTAURANT_VOUCHER”, where payment only occurs when the order is delivered to the customer and is made in person.
Possible Issues
Ticket Restaurant not accepted in payment request via paycomet
It may occur that a restaurant has payment failure when a payment request is registered via Ticket Restaurant. This problem may be related to the terminal IDs at the restaurant, which must be configured correctly to enable payment via restaurant ticket.
0 Comments