# PaymentForms



This document details the three components related to payments:
`NewPaymentForm`, `ExistingPaymentForm`, and `ReversePaymentForm`.

***

1. NewPaymentForm [#1-newpaymentform]

Purpose [#purpose]

The `NewPaymentForm` is used to create a new payment from an external
source (e.g., credit card, bank transfer) and apply it to a specific
invoice. The form is dynamic, rendering different fields based on the
payment `type` selected, as defined in the data model.

Usage [#usage]

```ts
import { NewPaymentForm } from './NewPaymentForm';
import { DataModel, CurrencyType } from '@socotra/ec-react-schemas';

const MakePaymentComponent = ({ dataModel, invoice }: { dataModel: DataModel, invoice: any }) => {
  const handleSubmit = (paymentRequest) => {
    console.log('New Payment Request:', paymentRequest);
    // Handle API call to process the new payment
  };

  return (
    <NewPaymentForm
      accountLocator={invoice.accountLocator}
      invoiceLocator={invoice.locator}
      invoiceBalance={invoice.balance}
      currency={invoice.currency as CurrencyType}
      dataModel={dataModel}
      handleSubmit={handleSubmit}
    />
  );
};
```

Props [#props]

| Prop             | Type                             | Description                                                     | Required |
| ---------------- | -------------------------------- | --------------------------------------------------------------- | -------- |
| `accountLocator` | `string`                         | The locator of the account associated with the payment.         | Yes      |
| `invoiceLocator` | `string`                         | The locator of the invoice being paid.                          | Yes      |
| `invoiceBalance` | `number`                         | The outstanding balance of the invoice.                         | Yes      |
| `currency`       | `CurrencyType`                   | The currency of the payment.                                    | Yes      |
| `dataModel`      | `DataModel`                      | The resolved data model containing payment type configurations. | Yes      |
| `handleSubmit`   | `(data: PaymentRequest) => void` | Callback with the `PaymentRequest` payload.                     | Yes      |

State Management [#state-management]

* The component initializes its state with the `invoiceBalance`
  pre-filled as the default payment `amount`.
* It holds all form data in a single state object.
* When the payment `type` is changed, the component intelligently
  resets the nested `data` object to avoid sending stale data from the
  previously selected type, while preserving the top-level default
  values.

Validation [#validation]

Validation is handled by [Ajv ](https://ajv.js.org/). A JSON schema is
built dynamically based on the fields defined for the selected payment
`type` in `dataModel.payments`.

Labels and Translations [#labels-and-translations]

**UI Labels**

Labels are customized via the `titles` prop.

| Key                 | Description                               | Default Value          |
| ------------------- | ----------------------------------------- | ---------------------- |
| `formTitle`         | The main title for the form.              | `''`                   |
| `type`              | Label for the “Payment Type” dropdown.    | `'Type'`               |
| `amount`            | Label for the “Amount” field.             | `'Amount'`             |
| `transactionMethod` | Label for the “Transaction Method” field. | `'Transaction Method'` |
| `transactionNumber` | Label for the “Transaction Number” field. | `'Transaction Number'` |
| `truthyLabel`       | Text for a “true” boolean value.          | `'Yes'`                |
| `falsyLabel`        | Text for a “false” boolean value.         | `'No'`                 |

***

2. ExistingPaymentForm [#2-existingpaymentform]

<span id="purpose-1" />

Purpose [#purpose-1]

The `ExistingPaymentForm` is used to apply a credit that already
exists on an account to an outstanding invoice. It is not for new
payments, but rather for distributing existing, unapplied funds.

<span id="usage-1" />

Usage [#usage-1]

```ts
import { ExistingPaymentForm } from './ExistingPaymentForm';

const ApplyCreditComponent = ({ account, invoice }: { account: any, invoice: any }) => {
  const handleSubmit = (creditDistributionRequest) => {
    console.log('Credit Distribution Request:', creditDistributionRequest);
    // Handle API call to apply the credit
  };

  return (
    <ExistingPaymentForm
      accountLocator={account.locator}
      invoiceLocator={invoice.locator}
      balance={account.unappliedCredit}
      invoiceBalance={invoice.balance}
      currency={invoice.currency}
      handleSubmit={handleSubmit}
    />
  );
};
```

<span id="props-1" />

Props [#props-1]

| Prop             | Type                                        | Description                                            | Required |
| ---------------- | ------------------------------------------- | ------------------------------------------------------ | -------- |
| `accountLocator` | `string`                                    | The locator of the account holding the credit.         | Yes      |
| `invoiceLocator` | `string`                                    | The locator of the invoice to apply the credit to.     | Yes      |
| `balance`        | `number`                                    | The available credit/unapplied balance on the account. | Yes      |
| `invoiceBalance` | `number`                                    | The outstanding balance of the target invoice.         | Yes      |
| `currency`       | `CurrencyType`                              | The currency of the transaction.                       | Yes      |
| `handleSubmit`   | `(data: CreditDistributionRequest) => void` | Callback with the `CreditDistributionRequest` payload. | Yes      |

<span id="state-management-1" />

State Management [#state-management-1]

The form’s state is simple, primarily managing the `amount` the user
wishes to apply. The `balance` and `invoiceBalance` fields are
displayed as read-only.

<span id="validation-1" />

Validation [#validation-1]

Validation is handled by [Ajv ](https://ajv.js.org/). The schema is
defined directly within the component and ensures the `amount` to
apply is greater than zero and does not exceed the available account
`balance`.

<span id="labels-and-translations-1" />

Labels and Translations [#labels-and-translations-1]

**UI Labels**

Labels are customized via the `titles` prop.

| Key              | Description                              | Default Value       |
| ---------------- | ---------------------------------------- | ------------------- |
| `formTitle`      | The main title for the form.             | `''`                |
| `invoiceBalance` | Label for the read-only invoice balance. | `'Invoice Balance'` |
| `balance`        | Label for the read-only account balance. | `'Balance'`         |
| `amountToApply`  | Label for the input field.               | `'Amount to Apply'` |

***

3. ReversePaymentForm [#3-reversepaymentform]

<span id="purpose-2" />

Purpose [#purpose-2]

The `ReversePaymentForm` is a simple form used to initiate the
reversal of a previously applied payment. Its main function is to
capture the reason for the reversal.

<span id="usage-2" />

Usage [#usage-2]

```ts
import { ReversePaymentForm } from './ReversePaymentForm';
import { DataModel } from '@socotra/ec-react-schemas';

const ReversePaymentComponent = ({ payment, dataModel }: { payment: any, dataModel: DataModel }) => {
  const handleSubmit = (reverseRequest) => {
    console.log('Payment Reversal Request:', reverseRequest);
    // Handle API call to reverse the payment
  };

  return (
    <ReversePaymentForm
      amount={payment.amount}
      currency={payment.currency}
      reversalTypes={dataModel.reversalTypes}
      handleSubmit={handleSubmit}
    />
  );
};
```

<span id="props-2" />

Props [#props-2]

| Prop            | Type                                               | Description                                                   | Required |
| --------------- | -------------------------------------------------- | ------------------------------------------------------------- | -------- |
| `amount`        | `number`                                           | The amount of the payment being reversed.                     | Yes      |
| `currency`      | `CurrencyType`                                     | The currency of the reversed payment.                         | Yes      |
| `reversalTypes` | `ReversalTypeConfigRecord`                         | The reversal type configurations from the data model.         | Yes      |
| `handleSubmit`  | `(data: CreditDistributionReverseRequest) => void` | Callback with the `CreditDistributionReverseRequest` payload. | Yes      |

<span id="state-management-2" />

State Management [#state-management-2]

The component’s state manages the selected `reversalType`. The
`amount` is displayed as a read-only field. The list of reversal
reasons is filtered to only show types that are not for new payments.

<span id="validation-2" />

Validation [#validation-2]

Validation is handled by [Ajv ](https://ajv.js.org/). The schema,
defined within the component, simply requires that a `reversalType` be
selected from the list.

<span id="labels-and-translations-2" />

Labels and Translations [#labels-and-translations-2]

**UI Labels**

Labels are customized via the `titles` prop.

| Key               | Description                             | Default Value           |
| ----------------- | --------------------------------------- | ----------------------- |
| `formTitle`       | The main title for the form.            | `''`                    |
| `amountToReverse` | Label for the read-only amount field.   | `'Amount to Reverse'`   |
| `reversalType`    | Label for the reversal reason dropdown. | `'Reason for Reverse?'` |
