# Embedded / Sale

# Shopfront Embedded Bridge Sale API

## Base Sale

The Shopfront Embedded Bridge Sale API revolves around a *Sale* object, this can be obtained and created in multiple
ways depending on what you're attempting to do.

> The device your embedded application is running on must always be a register in order to use the Sale API.

If you want to modify the current sale that is on the register, you'll want to look at the [Current Sale](#current-sale)
object.

If you want to create an arbitrary sale or find information about sales provided back from Shopfront through the 
Fulfilment API, you'll want to look at the [Sale](#sale) object.

Both of these objects extend from this `BaseSale` object. It contains the following methods that can be used to modify
the sale.

### getProducts

This will return all products that are currently on the sale. For more information about products,
refer to the [`SaleProduct` section](#product).

*Returns*

- `Array<SaleProduct>`

### getPayments

This will return all payments that are currently on the sale. For more information about payment,
refer to the [`SalePayment` section](#payment).

*Returns*

- `Array<SalePayment>`

### getCustomer

This will return the customer that is currently attached to the sale, if there is no customer, it
will return null. For more information on the customer, refer to the [`SaleCustomer` section](#customer).

*Returns*

- `SaleCustomer | null`

### getRegister

This will return the ID of the register that is currently attached to the sale. Rarely, there can be a circumstance
where there is no register currently attached the sale, this typically happens when you obtain a sale and the user
then swaps to no longer being in a register.

*Returns*

- `string | undefined`

### getClientId

This returns the current client ID which is attached to the sale, this ID is not guaranteed to be unique across the
Vendor as integrations can manually specify a client ID. If no client ID is provided for the sale, this will return
`null`

*Returns*

- `string | null`

### getSaleTotal

This is a shortcut method to obtain the total price for the sale.

*Returns*

- `number`

### getPaidTotal

This is a shortcut method to obtain the total amount of the sale which has already been paid for.

*Returns*

- `number`

### getSavingsTotal

Returns the total amount of savings that the sale has had applied to it.

*Returns*

- `number`

### getDiscountTotal

Returns the total discount that the sale has had applied to it.

*Returns*

- `number`

### getLinkedTo

Get the sale this is linked to, if it is not currently linked to a sale, this will be an empty string.

*Returns*

- `string`

### getRefundReason

Get the reason for providing a refund, if there is no reason, this will be an empty string.

*Returns*

- `string`

### getPriceSet

Determine the current price set which is being used on the sale, if it's the default price set this will be `null`. 

*Returns*

- `string | null`

### getExternalNote

Get the external sale note that is visible to customers.

*Returns*

- `string`

### getInternalNote

Similar to `getExternalNote`, this returns the internal note that is not visible to customers.

*Returns*

- `string`

### getOrderReference

Get the order reference that is set for this sale, this is visible to customers.

*Returns*

- `string`

### getMetaData

Get the meta data which has been applied to this sale. By default, Shopfront doesn't apply any, but this can be
used to attach arbitrary data from integrations to the sale.

*Returns*

- `Record<string, unknown>`

### addProduct

Add a product to the sale, if the sale is the current sale on the sell screen this product will automatically be 
consolidated into another if the following occurs:

- Another product with the same ID already exists,
- The product is a "normal" product (i.e. not a basket or package),
- The product's price has not been modified,
- The Vendor uses the "consolidate products" setting

| Field   | Type        | Description        |
|---------|-------------|--------------------|
| product | SaleProduct | The product to add |

*Returns*

- `Promise<void>`

**Add Product**

```javascript
import { SaleProduct } from "@shopfront/bridge";

const productToAdd = new SaleProduct("11e6...", 6);
await currentSale.addProduct(productToAdd);
```

### removeProduct

Remove a product from the sale, we would highly suggest passing in a product that has been retrieved
using the `getProducts` method.

| Field   | Type        | Description           |
|---------|-------------|-----------------------|
| product | SaleProduct | The product to remove |

*Returns*

- `Promise<void>`

**Remove Product**

```javascript
const products = currentSale.getProducts();

// Remove the second product line
const productToRemove = products[1];
await currentSale.removeProduct(productToRemove);
```

### addPayment

Add a payment to the sell screen.

If you specify a payment with a status, it will bypass the payment gateway (i.e. it won't request that
the user takes money from the customer).

If you don't specify a cashout amount, it will automatically determine if the payment method normally
requests cashout (from the payment method settings).

| Field   | Type        | Description        |
|---------|-------------|--------------------|
| payment | SalePayment | The payment to add |

*Returns*

- `Promise<void>`

**Add Payment**

```javascript
import { SalePayment } from "@shopfront/bridge";

const payment = new SalePayment("11e6...", 10.99);
await currentSale.addPayment(payment);
```

### addCustomer

Add a customer to the sale.

If there is already a customer on the sale, this will override that customer.

| Field    | Type         | Description         |
|----------|--------------|---------------------|
| customer | SaleCustomer | The customer to add |

*Returns*

- `Promise<void>`

**Add Customer**

```javascript
import { SaleCustomer } from "@shopfront/bridge";

const customer = new SaleCustomer("11e6...");
await currentSale.addCustomer(customer);
```

### removeCustomer

Remove a customer from the sale.

If there is no customer currently on the sale, this will be ignored.

If there are "on account" or loyalty payments still on the sale, this will be ignored.

*Returns*

- `Promise<void>`

### setExternalNote

Set the external note for the sale (this is visible by the customer).

| Field  | Type     | Description                                                          |
|--------|----------|----------------------------------------------------------------------|
| note   | string   | The note to apply to the sale                                        |
| append | boolean? | Whether to append the note to the current note (defaults to `false`) |

*Returns*

- `Promise<void>`

### setInternalNote

Set the internal note for the sale.

| Field  | Type     | Description                                                          |
|--------|----------|----------------------------------------------------------------------|
| note   | string   | The note to apply to the sale                                        |
| append | boolean? | Whether to append the note to the current note (defaults to `false`) |

*Returns*

- `Promise<void>`

### setOrderReference

Set the order reference for the sale (this is visible by the customer).

| Field     | Type   | Description                        |
|-----------|--------|------------------------------------|
| reference | string | The reference to apply to the sale |

*Returns*

- `Promise<void>`

### setMetaData

Set the meta data for the sale, this will override the previous meta data so we would highly suggest merging
it with the current meta data in case another integration has already modified the meta data.

| Field    | Type                    | Description                        |
|----------|-------------------------|------------------------------------|
| metaData | Record<string, unknown> | The meta data to apply to the sale |

*Returns*

- `Promise<void>`

### updateProduct

Update a product which already exists on the sale, we would highly suggest passing in a product that has been retrieved
using the `getProducts` method.

| Field   | Type        | Description        |
|---------|-------------|--------------------|
| product | SaleProduct | The product to add |

*Returns*

- `Promise<void>`

## Sale

This represents an arbitrary sale in Shopfront that may or may not have already been processed. It's guaranteed to not
be the current sale which is on the screen (to modify that, see the [Current Sale](#current-sale)). 

Whilst it's currently possible to create sales directly by initializing a new instance of this class, it is not
supported and functionality may change in the future without notice. We suggest only using this class when Shopfront
passes you the Sale explicitly (such as when the Fulfilment API is used).

It extends the [`BaseSale` object](#base-sale) and additionally implements the below methods. 

### removePayment

Remove a payment from the sale, we would highly suggest passing in a product that has been retrieved
using the `getPayments` method.

| Field   | Type        | Description           |
|---------|-------------|-----------------------|
| payment | SalePayment | The payment to remove |

*Returns*

- `Promise<void>`

### create

Create the sale in Shopfront, this adds the sale to the upload queue and prepares it to be uploaded at a future point,
it is not guaranteed that the sale will upload instantly (e.g. the current device may not have internet).

We would highly suggest checking the `success` return value and looking at the `message` if the sale was unsuccessful
as it means there was a validation error with the sale.

| Field       | Type        | Description                                                        |
|-------------|-------------|--------------------------------------------------------------------|
| application | Application | The application instance currently in communication with Shopfront |

*Returns*

- `Promise<{ success: boolean; message?: string }>`

## Current Sale

If the device your embedded application is running on is a register, you're able to modify
the current sale in progress using the Embedded Sale API.

To get started, you'll want to get the current sale by calling `application.getCurrentSale()`.
This method returns a promise that returns the sale currently on the sell screen (or if your
application isn't embedded on a register then it returns false).

The current sale extends the [`BaseSale` object](#base-sale) and additionally implements the below methods
which can be used once the current sale has been obtained.

**Sale**

```javascript
import { Bridge } from "@shopfront/bridge";

const application = Bridge.createApplication({
    // Your application details...
});

const currentSale = await application.getCurrentSale();
```

### refreshSale

This refreshes the sale to be the latest that exists on the sell screen, it will automatically
be called by any method that mutates the sale.

*Returns*

- `Promise<void>`

### cancelSale

Cancel the current sale, this will appear as a cancelled sale in the sales history and will appear
in action reports. It will also prevent further mutation of the sale.

*Returns*

- `Promise<void>`

### reversePayment

Reverse a payment on the sell screen. This is used to issue a refund to the customer.

The sale amount for the payment should be a positive figure.

| Field   | Type        | Description           |
|---------|-------------|-----------------------|
| payment | SalePayment | The payment to remove |

*Returns*

- `Promise<void>`

**Reverse Payment**

```javascript
const payments = currentSale.getPayments();

// Reverse the first payment
await currentSale.reversePayment(payments[0]);
```

## SaleProduct

The `SaleProduct` class is a representation of a product from Shopfront's internal sale state.
A `SaleProduct` will always have an *id* and a *quantity* whether created by you or from Shopfront.  

### Constructor

| Field        | Type           | Description                                                                    |
|--------------|----------------|--------------------------------------------------------------------------------|
| id           | string         | The ID of the product                                                          |
| quantity     | number         | The quantity of the product                                                    |
| price        | number?        | The price of the product, if not specified it will be automatically calculated |
| indexAddress | Array<number>? | The location of the product on the sell screen                                 |

### getId

Get the ID of the product

*Returns*

- `string`

### getMapped

Retrieve the original mapping ID of this product. This is typically only available when using the Fulfilment API.

*Returns*

- `string | undefined`

### getQuantity

Get the quantity of the product

*Returns*

- `number`

### getPrice

Get the price of the product

*Returns*

- `number | undefined`

### getIndexAddress

Get the index address of the product.

This is the internal address of where the product is in the sale. (e.g. if the address is
\[1, 3] it's the fourth product contained in the second sale line).

*Returns*

- `Array<number>`

### getName

Get the name of the product.

*Returns*

- `string | undefined`

### getType

Get the type of product this is.

*Returns*

- `"Normal" | "Basket" | "Package" | "Component" | "Voucher" | undefined`

### getTaxRateAmount

Get the tax rate amount.

This is the rate of the tax rate (e.g. 10 is a tax rate of 10%).

*Returns*

- `number | undefined`

### getNote

Get the sale note attached to this product.

*Returns*

- `string`

### getContains

Get the products that this product contains.

*Returns*

- `Array<SaleProduct>`

### getEdited

Get whether this product has been "edited".

Typically, being edited just means that the product has been discounted.

*Returns*

- `boolean`

### getCaseQuantity

Get the case quantity for this product.

*Returns*

- `number`

### getMetaData

Get the meta data that has been applied to this product

*Returns*

- `Record<string, unknown>`

### setMetaData

Set a meta data value for the product, this will override any value stored at the provided key
if applicable.

| Field | Type    | Description                            |
|-------|---------|----------------------------------------|
| key   | string  | The key of the meta data to update     |
| value | unknown | The value to update the meta data with |

> Note: You can specify `name.display.pre` and `name.display.post` (each dot is a nested object) to add additional
> information onto the receipts, sales history and sell screen

## SalePayment

The `SalePayment` class is a representation of a payment from Shopfront's internal sale state.
A `SalePayment` will always have an *id* and an *amount* whether created by you or from Shopfront.

### Constructor

| Field   | Type               | Description                                                                                                                                         |
|---------|--------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------|
| id      | string             | The ID of the payment method                                                                                                                        |
| amount  | number             | The amount to be paid on this method                                                                                                                |
| cashout | number?            | The amount of cash to be paid out from this method (added to the amount). If not provided then it uses the payment methods default cashout setting. |
| status  | SalePaymentStatus? | The status of the payment method, if provided it bypasses the payment gateway                                                                       |

### getId

Get the ID of the payment method.

*Returns*

- `string`

### getType

Get the type of payment method this is.

*Returns*

- `string`

### getStatus

Get the status of the payment.

*Returns*

- `SalePaymentStatus | undefined`

### getAmount

Get the value of this payment.

*Returns*

- `number`

### getCashout

Get the cashout amount paid (or to be paid) for this payment.

*Returns*

- `number`

### getRounding

Get the amount of rounding applied to this payment.

*Returns*

- `number`

## SaleCustomer

The `SaleCustomer` class is a representation of a customer from Shopfront's internal sale state.
A `SaleCustomer` will always have an *id* whether created by you or from Shopfront.

### Constructor

| Field | Type   | Description            |
|-------|--------|------------------------|
| id    | string | The ID of the customer |

### getId

Get the ID of the customer

*Returns*

- `string`