diff --git a/packages/esm-billing-app/src/billing.resource.ts b/packages/esm-billing-app/src/billing.resource.ts index 9fd036a1a..6b733daa4 100644 --- a/packages/esm-billing-app/src/billing.resource.ts +++ b/packages/esm-billing-app/src/billing.resource.ts @@ -23,7 +23,7 @@ export const useBills = (patientUuid?: string) => { patientUuid: bill?.patient?.uuid, status: bill?.status, receiptNumber: bill?.receiptNumber, - cashierName: bill?.cashier?.display, + cashier: bill?.cashier, cashPointUuid: bill?.cashPoint?.uuid, cashPointName: bill?.cashPoint?.name, cashPointLocation: bill?.cashPoint?.location?.display, @@ -66,7 +66,7 @@ export const useBill = (billUuid: string) => { patientUuid: bill?.patient?.uuid, status: bill?.status, receiptNumber: bill?.receiptNumber, - cashierName: bill?.cashier?.display, + cashier: bill?.cashier, cashPointUuid: bill?.cashPoint?.uuid, cashPointName: bill?.cashPoint?.name, cashPointLocation: bill?.cashPoint?.location?.display, @@ -91,3 +91,14 @@ export const useBill = (billUuid: string) => { mutate, }; }; + +export const processBillPayment = (payload, billUuid: string) => { + const url = `/ws/rest/v1/cashier/bill/${billUuid}`; + return openmrsFetch(url, { + method: 'POST', + body: payload, + headers: { + 'Content-Type': 'application/json', + }, + }); +}; diff --git a/packages/esm-billing-app/src/helpers/functions.ts b/packages/esm-billing-app/src/helpers/functions.ts index 76c25b23f..b93db0335 100644 --- a/packages/esm-billing-app/src/helpers/functions.ts +++ b/packages/esm-billing-app/src/helpers/functions.ts @@ -32,8 +32,15 @@ export function calculateTotalAmount(lineItems: Array) { } export const convertToCurrency = (amountToConvert: number) => { - if (amountToConvert === 0) { - return '--'; + const formatter = new Intl.NumberFormat('en-KE', { + style: 'currency', + currency: 'KES', + minimumFractionDigits: 2, + }); + let formattedAmount = formatter.format(Math.abs(amountToConvert)); + if (amountToConvert < 0) { + formattedAmount = `(${formattedAmount})`; } - return new Intl.NumberFormat('en-KE', { currency: 'KSH', style: 'currency' }).format(amountToConvert); + + return formattedAmount; }; diff --git a/packages/esm-billing-app/src/invoice/invoice-table.component.tsx b/packages/esm-billing-app/src/invoice/invoice-table.component.tsx index 260656b78..d0ad9ed7c 100644 --- a/packages/esm-billing-app/src/invoice/invoice-table.component.tsx +++ b/packages/esm-billing-app/src/invoice/invoice-table.component.tsx @@ -10,9 +10,11 @@ import { TableCell, DataTableSkeleton, } from '@carbon/react'; +import { Information } from '@carbon/react/icons'; import { isDesktop, useLayoutType } from '@openmrs/esm-framework'; import { useBill } from '../billing.resource'; import styles from './invoice-table.scss'; +import { useTranslation } from 'react-i18next'; type InvoiceTableProps = { billUuid: string; @@ -20,7 +22,15 @@ type InvoiceTableProps = { const InvoiceTable: React.FC = ({ billUuid }) => { const layout = useLayoutType(); + const { t } = useTranslation(); const responsiveSize = isDesktop(layout) ? 'sm' : 'lg'; + const tableTitle = t('lineItems', 'Line items'); + const tableDescription = ( +

+ {t('lineItemsToBeBilled', 'Line items to be billed')} + +

+ ); const { bill, isLoading } = useBill(billUuid); const headerData = [ { header: 'No', key: 'no' }, @@ -32,18 +42,19 @@ const InvoiceTable: React.FC = ({ billUuid }) => { { header: 'Total', key: 'total' }, ]; - const rowData = bill?.lineItems?.map((item, index) => { - return { - no: `${index + 1}`, - id: `${item.uuid}`, - billItem: item.item, - billCode: bill.receiptNumber, - status: bill.status, - quantity: item.quantity, - price: item.price, - total: item.price * item.quantity, - }; - }); + const rowData = + bill?.lineItems?.map((item, index) => { + return { + no: `${index + 1}`, + id: `${item.uuid}`, + billItem: item.item, + billCode: bill.receiptNumber, + status: bill.status, + quantity: item.quantity, + price: item.price, + total: item.price * item.quantity, + }; + }) ?? []; if (isLoading) { return ( @@ -62,8 +73,8 @@ const InvoiceTable: React.FC = ({ billUuid }) => { return (
- {({ rows, headers, getRowProps, getTableProps }) => ( - + {({ rows, headers, getRowProps, getTableProps, getToolbarProps }) => ( + diff --git a/packages/esm-billing-app/src/invoice/invoice-table.scss b/packages/esm-billing-app/src/invoice/invoice-table.scss index 859703c1e..2ebd4005e 100644 --- a/packages/esm-billing-app/src/invoice/invoice-table.scss +++ b/packages/esm-billing-app/src/invoice/invoice-table.scss @@ -1,7 +1,27 @@ @use '@carbon/colors'; @use '@carbon/layout'; @use '@carbon/type'; +@import '~@openmrs/esm-styleguide/src/vars'; .invoiceContainer { - margin: 0 layout.$spacing-05; + margin: 0 layout.$spacing-05 layout.$spacing-05 layout.$spacing-05; +} + +.tableDescription { + display: flex; + align-items: flex-start; + margin-top: layout.$spacing-02; + column-gap: layout.$spacing-01; + + ::after { + content: ''; + display: block; + width: 2rem; + padding-top: 0.188rem; + border-bottom: 0.375rem solid var(--brand-03); + } + + & > span { + @include type.type-style('body-01'); + } } diff --git a/packages/esm-billing-app/src/invoice/invoice.component.tsx b/packages/esm-billing-app/src/invoice/invoice.component.tsx index 7f55271db..da9436f56 100644 --- a/packages/esm-billing-app/src/invoice/invoice.component.tsx +++ b/packages/esm-billing-app/src/invoice/invoice.component.tsx @@ -1,43 +1,32 @@ import React from 'react'; -import { Button, InlineLoading } from '@carbon/react'; -import { ArrowLeft } from '@carbon/react/icons'; -import { ExtensionSlot, isDesktop, navigate, useLayoutType, usePatient } from '@openmrs/esm-framework'; +import { InlineLoading } from '@carbon/react'; +import { ExtensionSlot, usePatient } from '@openmrs/esm-framework'; import { useParams } from 'react-router-dom'; import styles from './invoice.scss'; import InvoiceTable from './invoice-table.component'; import Payments from './payments/payments.component'; -import { useTranslation } from 'react-i18next'; import { useBill } from '../billing.resource'; +import { convertToCurrency } from '../helpers'; +import { ErrorState } from '@openmrs/esm-patient-common-lib'; +import { useTranslation } from 'react-i18next'; type InvoiceProps = {}; const Invoice: React.FC = () => { const params = useParams(); - const layout = useLayoutType(); + const { t } = useTranslation(); const { patient, patientUuid, isLoading } = usePatient(params?.patientUuid); - const { bill } = useBill(params?.billUuid); + const { bill, isLoading: isLoadingBilling, error } = useBill(params?.billUuid); const invoiceDetails = { - 'Total Amount': bill?.totalAmount, - 'Amount Tendered': bill?.tenderedAmount, + 'Total Amount': convertToCurrency(bill?.totalAmount), + 'Amount Tendered': convertToCurrency(bill?.tenderedAmount), 'Invoice Number': bill.receiptNumber, 'Date And Time': bill?.dateCreated, 'Invoice Status': bill?.status, }; - const invoiceTotal = { - 'Total Amount': bill?.totalAmount, - 'Amount Tendered': bill?.tenderedAmount, - 'Discount Amount': 0, - 'Amount due': bill?.totalAmount - bill?.tenderedAmount, - }; - - const navigateToDashboard = () => - navigate({ - to: window.getOpenmrsSpaBase() + 'home/billing', - }); - - if (isLoading) { + if (isLoading && isLoadingBilling) { return (
= () => { ); } + if (error) { + return ; + } + return (
- + {patient && patientUuid && }
{Object.entries(invoiceDetails).map(([key, val]) => ( ))}
-
- -
-
-
- -
- {Object.entries(invoiceTotal).map(([key, val]) => ( - - ))} -
-
+ {bill && }
); @@ -100,18 +75,3 @@ function InvoiceDetails({ label, value }: InvoiceDetailsProps) { } export default Invoice; - -interface InvoicePaymentBreakdown { - label: string; - value: number; -} - -function InvoicePaymentBreakdown({ label, value }: InvoicePaymentBreakdown) { - const { t } = useTranslation(); - - return ( -
- {label} : {value} -
- ); -} diff --git a/packages/esm-billing-app/src/invoice/payments/invoice-breakdown/invoice-breakdown.component.tsx b/packages/esm-billing-app/src/invoice/payments/invoice-breakdown/invoice-breakdown.component.tsx new file mode 100644 index 000000000..805bb711c --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/invoice-breakdown/invoice-breakdown.component.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import styles from './invoice-breakdown.scss'; + +type InvoiceBreakDownProps = { + label: string; + value: string; +}; + +export const InvoiceBreakDown: React.FC = ({ label, value }) => { + return ( +
+ {label} : + {value} +
+ ); +}; diff --git a/packages/esm-billing-app/src/invoice/payments/invoice-breakdown/invoice-breakdown.scss b/packages/esm-billing-app/src/invoice/payments/invoice-breakdown/invoice-breakdown.scss new file mode 100644 index 000000000..fed6719c5 --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/invoice-breakdown/invoice-breakdown.scss @@ -0,0 +1,24 @@ +@use '@carbon/colors'; +@use '@carbon/layout'; +@use '@carbon/type'; + +.invoiceBreakdown { + display: grid; + grid-template-columns: 1fr 1fr; + align-items: flex-end; +} + +.label { + @include type.type-style('heading-02'); + color: colors.$gray-70; + margin: layout.$spacing-01; + text-align: end; +} + +.value { + @include type.type-style('heading-02'); + margin-top: layout.$spacing-04; + text-align: start; + margin-left: layout.$spacing-02; + color: colors.$black; +} diff --git a/packages/esm-billing-app/src/invoice/payments/payment-form/payment-form.component.tsx b/packages/esm-billing-app/src/invoice/payments/payment-form/payment-form.component.tsx new file mode 100644 index 000000000..ac4931cca --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/payment-form/payment-form.component.tsx @@ -0,0 +1,104 @@ +import React, { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; +import { TrashCan, Add } from '@carbon/react/icons'; +import { Button, Dropdown, TextInput, NumberInputSkeleton } from '@carbon/react'; +import { Controller, useFieldArray, useFormContext } from 'react-hook-form'; +import styles from './payment-form.scss'; +import { usePaymentModes } from '../payment.resource'; +import { ErrorState } from '@openmrs/esm-patient-common-lib'; +import { PaymentFormValue } from '../payments.component'; + +type PaymentFormProps = { disablePayment: boolean }; + +const DEFAULT_PAYMENT = { method: '', amount: 0, referenceCode: '' }; + +const PaymentForm: React.FC = ({ disablePayment }) => { + const { t } = useTranslation(); + const { + control, + formState: { errors }, + } = useFormContext(); + const { paymentModes, isLoading, error } = usePaymentModes(); + const { fields, remove, append } = useFieldArray({ name: 'payment', control: control }); + + const handleAppendPaymentMode = useCallback(() => append(DEFAULT_PAYMENT), [append]); + const handleRemovePaymentMode = useCallback((index) => remove(index), [remove]); + if (isLoading) { + return ; + } + if (error) { + return ( +
+ +
+ ); + } + + return ( +
+ {fields.map((field, index) => ( +
+ ( + field.onChange(selectedItem.uuid)} + titleText={t('paymentMethod', 'Payment method')} + label={t('selectPaymentMethod', 'Select payment method')} + items={paymentModes} + itemToString={(item) => (item ? item.name : '')} + invalid={!!errors?.payment?.[index]?.method} + invalidText={errors?.payment?.[index]?.method?.message} + /> + )} + /> + ( + + )} + /> + + ( + + )} + /> + + +
+ ))} + +
+ ); +}; + +export default PaymentForm; diff --git a/packages/esm-billing-app/src/invoice/payments/payment-form/payment-form.scss b/packages/esm-billing-app/src/invoice/payments/payment-form/payment-form.scss new file mode 100644 index 000000000..c8a37c8b2 --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/payment-form/payment-form.scss @@ -0,0 +1,44 @@ +@use '@carbon/colors'; +@use '@carbon/layout'; +@use '@carbon/type'; + +.paymentContainer { + margin: layout.$layout-01; + padding: layout.$layout-01; + width: 70%; + border-right: 1px solid colors.$cool-gray-40; +} + +.paymentButtons { + margin: layout.$layout-01 0; +} + +.paymentMethodContainer { + display: grid; + grid-template-columns: repeat(4, 1fr); + align-items: flex-start; + column-gap: 1rem; + margin: 0.625rem 0; + width: 100%; +} + +.paymentTotals { + margin-top: layout.$spacing-01; +} + +.processPayments { + display: flex; + justify-content: flex-end; + margin: layout.$spacing-05; + column-gap: layout.$spacing-04; +} + +.errorPaymentContainer { + margin: layout.$spacing-04; + min-height: layout.$spacing-09; +} + +.removeButton { + align-self: center; + margin-top: layout.$spacing-03; +} diff --git a/packages/esm-billing-app/src/invoice/payments/payment-history/payment-history.component.tsx b/packages/esm-billing-app/src/invoice/payments/payment-history/payment-history.component.tsx new file mode 100644 index 000000000..2de434a75 --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/payment-history/payment-history.component.tsx @@ -0,0 +1,68 @@ +import React from 'react'; +import { DataTable, Table, TableHead, TableRow, TableHeader, TableBody, TableCell } from '@carbon/react'; +import { MappedBill } from '../../../types'; +import { formatDate } from '@openmrs/esm-framework'; +import { convertToCurrency } from '../../../helpers'; + +type PaymentHistoryProps = { + bill: MappedBill; +}; + +const PaymentHistory: React.FC = ({ bill }) => { + const headers = [ + { + key: 'dateCreated', + header: 'Date of payment', + }, + { + key: 'amount', + header: 'Bill amount', + }, + { + key: 'amountTendered', + header: 'Amount tendered', + }, + { + key: 'paymentMethod', + header: 'Payment method', + }, + ]; + const rows = bill?.payments?.map((payment) => ({ + id: `${payment.uuid}`, + dateCreated: formatDate(new Date(payment.dateCreated)), + amountTendered: convertToCurrency(payment.amountTendered), + amount: convertToCurrency(payment.amount), + paymentMethod: payment.instanceType.name, + })); + + if (Object.values(bill?.payments ?? {}).length === 0) { + return; + } + + return ( + + {({ rows, headers, getTableProps, getHeaderProps, getRowProps }) => ( +
+ + + {headers.map((header) => ( + {header.header} + ))} + + + + {rows.map((row) => ( + + {row.cells.map((cell) => ( + {cell.value} + ))} + + ))} + +
+ )} +
+ ); +}; + +export default PaymentHistory; diff --git a/packages/esm-billing-app/src/invoice/payments/payment-methods.scss b/packages/esm-billing-app/src/invoice/payments/payment-methods.scss deleted file mode 100644 index 655fb03d7..000000000 --- a/packages/esm-billing-app/src/invoice/payments/payment-methods.scss +++ /dev/null @@ -1,5 +0,0 @@ -.paymentMethodContainer { - display: flex; - align-items: center; - column-gap: 1rem; -} diff --git a/packages/esm-billing-app/src/invoice/payments/payment-options.component.tsx b/packages/esm-billing-app/src/invoice/payments/payment-options.component.tsx deleted file mode 100644 index c2e6dbe4f..000000000 --- a/packages/esm-billing-app/src/invoice/payments/payment-options.component.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import React from 'react'; -import { ComboBox, TextInput } from '@carbon/react'; -import { useTranslation } from 'react-i18next'; -import styles from './payment-methods.scss'; - -type PaymentOptionsProps = {}; - -const PaymentOptions: React.FC = () => { - const { t } = useTranslation(); - return ( -
- {}} - id="paymentMethod" - items={[ - { id: 'MPESA', text: 'MPESA' }, - { id: 'CASH', text: 'CASH' }, - { id: 'BANKDEPOSIT', text: 'BANK DEPOSIT' }, - ]} - itemToString={(item) => (item ? item.text : '')} - titleText={t('paymentMethod', 'Payment method')} - /> - - -
- ); -}; - -export default PaymentOptions; diff --git a/packages/esm-billing-app/src/invoice/payments/payment.resource.ts b/packages/esm-billing-app/src/invoice/payments/payment.resource.ts new file mode 100644 index 000000000..430a6ed2e --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/payment.resource.ts @@ -0,0 +1,29 @@ +import useSWR from 'swr'; +import { openmrsFetch } from '@openmrs/esm-framework'; + +type PaymentMethod = { + uuid: string; + description: string; + name: string; + retired: boolean; +}; + +const swrOption = { + errorRetryCount: 2, +}; + +export const usePaymentModes = () => { + const url = `/ws/rest/v1/cashier/paymentMode`; + const { data, isLoading, error, mutate } = useSWR<{ data: { results: Array } }>( + url, + openmrsFetch, + swrOption, + ); + + return { + paymentModes: data?.data?.results ?? [], + isLoading, + mutate, + error, + }; +}; diff --git a/packages/esm-billing-app/src/invoice/payments/payments.component.tsx b/packages/esm-billing-app/src/invoice/payments/payments.component.tsx index e0ef2aede..24f9c3c2a 100644 --- a/packages/esm-billing-app/src/invoice/payments/payments.component.tsx +++ b/packages/esm-billing-app/src/invoice/payments/payments.component.tsx @@ -1,34 +1,105 @@ -import React, { useState } from 'react'; +import React from 'react'; import { Button } from '@carbon/react'; -import { Add } from '@carbon/react/icons'; -import styles from './payments.scss'; +import { navigate, showSnackbar } from '@openmrs/esm-framework'; import { useTranslation } from 'react-i18next'; import { CardHeader } from '@openmrs/esm-patient-common-lib'; -import PaymentOptions from './payment-options.component'; +import { FormProvider, useForm, useWatch } from 'react-hook-form'; +import { convertToCurrency } from '../../helpers'; +import { InvoiceBreakDown } from './invoice-breakdown/invoice-breakdown.component'; +import { MappedBill } from '../../types'; +import PaymentHistory from './payment-history/payment-history.component'; +import styles from './payments.scss'; +import PaymentForm from './payment-form/payment-form.component'; +import { createPaymentPayload } from './utils'; +import { processBillPayment } from '../../billing.resource'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { z } from 'zod'; -type PaymentProps = {}; +const paymentSchema = z.object({ + method: z.string().refine((value) => !!value, 'Payment method is required'), + amount: z.union([ + z.number().refine((value) => !!value, 'Amount is required'), + z.string().refine((value) => !!value, 'Amount is required'), + ]), + referenceCode: z.union([z.number(), z.string()]).optional(), +}); +const paymentFormSchema = z.object({ payment: z.array(paymentSchema) }); -const Payments: React.FC = () => { +type PaymentProps = { bill: MappedBill }; +export type Payment = { method: string; amount: string | number; referenceCode?: number | string }; +export type PaymentFormValue = { + payment: Array; +}; + +const Payments: React.FC = ({ bill }) => { const { t } = useTranslation(); - const [paymentControls, setPaymentControls] = useState([]); + const methods = useForm({ + mode: 'all', + defaultValues: {}, + resolver: zodResolver(paymentFormSchema), + }); + + const formValues = useWatch({ + name: 'payment', + control: methods.control, + }); + + const totalAmountTendered = formValues?.reduce((curr: number, prev) => curr + Number(prev.amount) ?? 0, 0) ?? 0; + const amountDue = Number(bill.totalAmount) - (Number(bill.tenderedAmount) + Number(totalAmountTendered)); + const handleNavigateToBillingDashboard = () => + navigate({ + to: window.getOpenmrsSpaBase() + 'home/billing', + }); + + const handleProcessPayment = () => { + const paymentPayload = createPaymentPayload(bill, bill.patientUuid, formValues, amountDue); + processBillPayment(paymentPayload, bill.uuid).then( + (resp) => { + showSnackbar({ + title: t('Bill payment'), + subtitle: 'Bill payment processing has been successful', + kind: 'success', + timeoutInMs: 3000, + }); + handleNavigateToBillingDashboard(); + }, + (error) => { + showSnackbar({ title: 'Bill payment error', kind: 'error', subtitle: error }); + }, + ); + }; + return ( -
- - - - -
- {paymentControls.map((el) => ( - - ))} + +
+
+ + + +
+ {bill && } + +
+
+
+ + + + +
+
+
+ +
-
+ ); }; diff --git a/packages/esm-billing-app/src/invoice/payments/payments.scss b/packages/esm-billing-app/src/invoice/payments/payments.scss index 74d14e4c4..d9dfab7f4 100644 --- a/packages/esm-billing-app/src/invoice/payments/payments.scss +++ b/packages/esm-billing-app/src/invoice/payments/payments.scss @@ -2,6 +2,10 @@ @use '@carbon/layout'; @use '@carbon/type'; +.wrapper { + display: flex; +} + .paymentContainer { margin: layout.$layout-01; padding: layout.$layout-01; @@ -12,3 +16,22 @@ .paymentButtons { margin: layout.$layout-01 0; } + +.paymentMethodContainer { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + align-items: flex-end; + column-gap: 1rem; + margin: 0.625rem 0; +} + +.paymentTotals { + margin-top: layout.$spacing-01; +} + +.processPayments { + display: flex; + justify-content: flex-end; + margin: layout.$spacing-05; + column-gap: layout.$spacing-04; +} diff --git a/packages/esm-billing-app/src/invoice/payments/utils.ts b/packages/esm-billing-app/src/invoice/payments/utils.ts new file mode 100644 index 000000000..a85be9b44 --- /dev/null +++ b/packages/esm-billing-app/src/invoice/payments/utils.ts @@ -0,0 +1,29 @@ +import { MappedBill } from '../../types'; +import { Payment } from './payments.component'; + +export const createPaymentPayload = ( + bill: MappedBill, + patientUuid: string, + formValues: Array, + amountDue: number, +) => { + const { cashier } = bill; + const totalAmount = bill?.totalAmount; + const paymentStatus = amountDue <= 0 ? 'PAID' : 'PENDING'; + + const billPayment = formValues.map((formValue) => ({ + amount: parseFloat(totalAmount.toFixed(2)), + amountTendered: parseFloat(Number(formValue.amount).toFixed(2)), + attributes: [], + instanceType: formValue.method, + })); + const processedPayment = { + cashPoint: bill.cashPointUuid, + cashier: cashier.uuid, + payments: [...billPayment], + patient: patientUuid, + status: paymentStatus, + }; + + return processedPayment; +}; diff --git a/packages/esm-billing-app/src/metrics-cards/metrics.resource.ts b/packages/esm-billing-app/src/metrics-cards/metrics.resource.ts index 30d46fa61..847b52fb6 100644 --- a/packages/esm-billing-app/src/metrics-cards/metrics.resource.ts +++ b/packages/esm-billing-app/src/metrics-cards/metrics.resource.ts @@ -26,7 +26,7 @@ export const useBillMetrics = (bills: Array) => { const paidBills = bills .flatMap((bill) => bill.payments) - .flatMap((payment) => payment.amount) + .flatMap((payment) => payment.amountTendered) .reduce((prev, curr) => curr + prev, 0); const cumulativeBills = calculateTotals(); diff --git a/packages/esm-billing-app/src/types/index.ts b/packages/esm-billing-app/src/types/index.ts index deb65a04b..ba3096b6b 100644 --- a/packages/esm-billing-app/src/types/index.ts +++ b/packages/esm-billing-app/src/types/index.ts @@ -6,7 +6,7 @@ export interface MappedBill { cashPointUuid: string; cashPointName: string; cashPointLocation: string; - cashierName: string; + cashier: Provider; receiptNumber: string; status: string; identifier: string;