# Offset
Offset is a very important process for BCP. It’s a process to settle AR/AP and reduce AR/AP balance to 0. 

## API List
*  /bcp-core/offset/v1/arapOffse
*  /bcp-core/offset/v1/toleranceOffset
*  /bcp-core/offset/v1/reverseOffset

## ARAP Offset API

### API Path
/bcp-core/offset/v1/arapOffse

### Business Usage
The ARAP Offset API is used in BCP for AR/AP netting. It performs internal offset between Accounts Receivable (AR) and Accounts Payable (AP) without creating any real collection or payment. Multiple AR/AP entries can be offset against each other, reducing their balances and generating corresponding Offset / OffsetDetail records. This is the standard AR/AP netting capability in BCP.

#### Typical Business Scenarios

* Clear AR/AP for canceled inception without actual payment 

For policies that have been canceled and where no real collection or payment has happened, this API can offset the related AR/AP entries internally so that the business is cleared to zero in BCP while keeping the accounting trail.

* Netting adjustment AR/AP after later corrections

When the business system sends endorsements, reversals, or other adjustments that create opposite-direction AR/AP entries, this API can net the original AR/AP against the adjustment AR/AP, keeping the financial records clean and consistent.

### Dynamic Fields
This API supports dynamic fields, which can be flexibly configured through the dynamicProperties object. Please note that dynamic fields need to be configured in the Data Dictionary of the Offset in advance, otherwise the API will report an error stating that the field does not exist.


### API Sample
  Sample Request
  ```json
{
	"Amount": 1004.4,
	"ArapList": [{
		"@pk": 10181400012,
		"@type": "BcpArap-Arap",
		"Amount": 1004.4,
		"ArapCate": "2",
		"ArapId": "10181400012,1961843BA76E325518AC80E8E98E6C71",
		"ArapNo": "CR20240300000399",
		"ArapStatus": "1",
		"ArapType": "-1001",
		"Balance": 1004.4,
		"BizTransId": "10181400010,D86C6BDE81AB2116046BC6A8F0070854",
		"BookingCurrencyCode": "USD",
		"BusinessObjectId": 1100002651088,
		"Commission": -93,
		"CorrespondingCommissionAmount": 0,
		"CurrencyCode": "USD",
		"CurrentPeriod": 1,
		"DirectBookingEr": 1,
		"DirectEr": 1,
		"DueDate": "2024-03-23",
		"GenerateDate": "2024-03-22T15:41:16",
		"HasMandate": "N",
		"HasNote": "N",
		"IsApproved": "N",
		"IsOffsetByCommission": "N",
		"LocalCurrencyCode": "USD",
		"NeedStatement": "N",
		"OffsetAmount": -1004.4,
		"OffsetByCommissionAmount": 0,
		"OperateTime": "2024-03-22T15:41:16",
		"PayerPayeeName": "ArapOffset",
		"PayerPayeeType": "IndiCustomer",
		"PaymentMethod": "100",
		"PeriodEndDate": "2024-03-23",
		"PeriodStartDate": "2024-03-23",
		"RefFeeId": 10181400011,
		"Tax": -74.4,
		"TotalPeriods": 1,
		"Transaction": {
			"@pk": 10181400010,
			"@type": "BcpBizTransaction-BizTransaction",
			"BizModule": "10",
			"BizSource": "1",
			"BizTransId": "10181400010,D86C6BDE81AB2116046BC6A8F0070854",
			"BizTransTime": "2024-03-22T15:41:14",
			"BizTransType": "ENDORSEMENT",
			"BizUniqueId": "10181520018,EC0D68482002DF36E3A35890BCEB1D46",
			"BookingCurrencyCode": "USD",
			"BranchCode": "10001",
			"BranchName": "xxxxxx",
			"BusinessObjectId": 1100002651370,
			"ChannelCode": "PTY10000054541003",
			"ChannelName": "Sales",
			"ChannelType": "14",
			"ChannelTypeName": "Agent Company",
			"CurrencyCode": "USD",
			"DirectBookingEr": 0.79,
			"DirectEr": 1,
			"HasMandate": "N",
			"LocalCurrencyCode": "USD",
			"PaymentMethod": "100",
			"PaymentType": "1",
			"PolicyHolderName": "ArapOffset",
			"PolicyNo": "POTBTI01233991",
			"ProductCode": "TBTI",
			"ProductLineCode": "Travel",
			"ProductName": "API TEST",
			"RefTransId": "10181520018,EC0D68482002DF36E3A35890BCEB1D46",
			"RefTransNo": "POTBTI01233991-001",
			"TotalPeriods": 1
		},
		"VersionSeq": 1,
		"NewBalance": 0,
		"Selected": "true"
	}, {
		"@pk": 10181390021,
		"@type": "BcpArap-Arap",
		"Amount": 1004.4,
		"ArapCate": "1",
		"ArapId": "10181390021,02523D2D140D797E697DA1DAB64072FF",
		"ArapNo": "DR20240300003263",
		"ArapStatus": "1",
		"ArapType": "-1001",
		"Balance": 1004.4,
		"BizTransId": "10181390019,ED604D23B99BF5A0DEB13DEF4F3EA85E",
		"BookingCurrencyCode": "USD",
		"BusinessObjectId": 1100002651088,
		"Commission": 93,
		"CorrespondingCommissionAmount": 0,
		"CurrencyCode": "USD",
		"CurrentPeriod": 1,
		"DirectBookingEr": 1,
		"DirectEr": 1,
		"DueDate": "2024-03-23",
		"GenerateDate": "2024-03-22T15:41:06",
		"HasMandate": "N",
		"HasNote": "N",
		"IsApproved": "N",
		"IsOffsetByCommission": "N",
		"LocalCurrencyCode": "USD",
		"NeedStatement": "N",
		"OffsetAmount": 1004.4,
		"OffsetByCommissionAmount": 0,
		"OperateTime": "2024-03-22T15:41:06",
		"PayerPayeeName": "ArapOffset",
		"PayerPayeeType": "IndiCustomer",
		"PaymentMethod": "100",
		"PeriodEndDate": "2024-03-23",
		"PeriodStartDate": "2024-03-23",
		"RefFeeId": 10181390020,
		"Tax": 74.4,
		"TotalPeriods": 1,
		"Transaction": {
			"@pk": 10181390019,
			"@type": "BcpBizTransaction-BizTransaction",
			"BizModule": "10",
			"BizSource": "1",
			"BizTransId": "10181390019,ED604D23B99BF5A0DEB13DEF4F3EA85E",
			"BizTransTime": "2024-03-22T15:41:06",
			"BizTransType": "NEWBIZ",
			"BizUniqueId": "10181490010,C46F83BBCD721DF242846B73F614CD1A",
			"BookingCurrencyCode": "USD",
			"BranchCode": "10001",
			"BranchName": "xxxxxx",
			"BusinessObjectId": 1100002651370,
			"ChannelCode": "PTY10000054541003",
			"ChannelName": "Sales",
			"ChannelType": "14",
			"ChannelTypeName": "Agent Company",
			"CurrencyCode": "USD",
			"DirectBookingEr": 0.79,
			"DirectEr": 1,
			"HasMandate": "N",
			"LocalCurrencyCode": "USD",
			"PaymentMethod": "100",
			"PaymentType": "1",
			"PolicyHolderName": "ArapOffset",
			"PolicyNo": "POTBTI01233991",
			"ProductCode": "TBTI",
			"ProductLineCode": "Travel",
			"ProductName": "API TEST",
			"RefTransId": "10181490010,C46F83BBCD721DF242846B73F614CD1A",
			"RefTransNo": "POTBTI01233991",
			"TotalPeriods": 1
		},
		"VersionSeq": 1,
		"NewBalance": 0,
		"Selected": "true"
	}],
	"OffsetType": 1,
	"CurrencyCode": "USD",
	"DynamicFieldMap": {
       "CustomerField001":"Field001",
       "CustomerField002":"Field002"
	}
}
  
  ```
  
  Sample Response
  ```json
  {
    "Model": [
        {
            "@pk": 10181390025,
            "@type": "BcpOffset-Offset",
            "Amount": 1004.4,
            "ApplicationNo": "SUSP20240300000054",
            "BookingCurrencyCode": "USD",
            "BusinessObjectId": 1100002652393,
            "CurrencyCode": "USD",
            "DetailList": [
                {
                    "@pk": 10181390026,
                    "@type": "BcpOffsetDetail-OffsetDetail",
                    "Amount": 1004.4,
                    "BookingCurrencyCode": "USD",
                    "BusinessObjectId": 1100002652469,
                    "CurrencyCode": "USD",
                    "DirectBookingEr": 1,
                    "DirectEr": 1,
                    "LocalCurrencyCode": "USD",
                    "OffsetDetailId": 10181390026,
                    "RefId": "10181400012,1961843BA76E325518AC80E8E98E6C71",
                    "RefType": "3"
                },
                {
                    "@pk": 10181390027,
                    "@type": "BcpOffsetDetail-OffsetDetail",
                    "Amount": 1004.4,
                    "BookingCurrencyCode": "USD",
                    "BusinessObjectId": 1100002652469,
                    "CurrencyCode": "USD",
                    "DirectBookingEr": 1,
                    "DirectEr": 1,
                    "LocalCurrencyCode": "USD",
                    "OffsetDetailId": 10181390027,
                    "RefId": "10181390024,886E98C49CC152433A566F709B77BEB5",
                    "RefType": "2"
                },
                {
                    "@pk": 10181390031,
                    "@type": "BcpOffsetDetail-OffsetDetail",
                    "Amount": 1004.4,
                    "BookingCurrencyCode": "USD",
                    "BusinessObjectId": 1100002652469,
                    "CurrencyCode": "USD",
                    "DirectBookingEr": 1,
                    "DirectEr": 1,
                    "LocalCurrencyCode": "USD",
                    "OffsetDetailId": 10181390031,
                    "RefId": "10181390021,02523D2D140D797E697DA1DAB64072FF",
                    "RefType": "3"
                },
                {
                    "@pk": 10181390032,
                    "@type": "BcpOffsetDetail-OffsetDetail",
                    "Amount": 1004.4,
                    "BookingCurrencyCode": "USD",
                    "BusinessObjectId": 1100002652469,
                    "CurrencyCode": "USD",
                    "DirectBookingEr": 1,
                    "DirectEr": 1,
                    "LocalCurrencyCode": "USD",
                    "OffsetDetailId": 10181390032,
                    "RefId": "10181390024,886E98C49CC152433A566F709B77BEB5",
                    "RefType": "2"
                }
            ],
            "DirectBookingEr": 1,
            "DirectEr": 1,
            "HasNote": "N",
            "LocalCurrencyCode": "USD",
            "OffsetBy": 10000001178005,
            "OffsetCurrencyCode": "USD",
            "OffsetId": "10181390025,ABD707A2C6077777F677D607DE5095AF",
            "OffsetNo": "OFS20240300000050",
            "OffsetStatus": "1",
            "OffsetTime": "2024-03-22T15:45:07",
            "OffsetType": "1",
            "VersionSeq": 1,
            "CustomerField001":"Field001",
            "CustomerField002":"Field002"
        }
    ],
    "Status": "OK"
}
  ```
### Internal Data Behavior

The business models involved in the ARAP offset operation have the following relationships:
1.	Generate a piece of total accounting information `BcpSuspense`. 
2.	Offset the ARAP selected in the UI.

### What You Can Extend
After completing the ARAP offset, it is necessary to transmit data back to the business party.

## Tolerance Offset API
### API Path
/bcp-core/offset/v1/toleranceOffset

### Business Usage
Tolerance is usually used to offset that tiny amount of money. For example, a policy with a premium amount of 100.01, where the customer is only asked to pay 100, is a common practice for convenience.

Write-offs are used to offset bad debts that are deemed uncollectible.

### API Sample
  Sample Request
  ```json
  {
	"OffsetType": 3,
	"ArapList": [{
		"@pk": 874333535,
		"@type": "BcpArap-Arap",
		"Amount": 1004.4,
		"ArapCate": "1",
		"ArapId": 874333535,
		"ArapNo": "DR20240500000128",
		"ArapStatus": "1",
		"ArapType": "-1001",
		"Balance": 1004.4,
		"BizTransId": 874333533,
		"BookingCurrencyCode": "USD",
		"BusinessObjectId": 1100002651088,
		"Commission": 93,
		"CorrespondingCommissionAmount": 0,
		"CurrencyCode": "USD",
		"CurrentPeriod": 1,
		"DirectBookingEr": 1,
		"DirectEr": 1,
		"DueDate": "2024-05-22",
		"GenerateDate": "2024-05-21T11:28:53",
		"HasMandate": "N",
		"HasNote": "N",
		"IsApproved": "N",
		"IsOffsetByCommission": "N",
		"LocalCurrencyCode": "BRL",
		"NeedStatement": "N",
		"OffsetAmount": 1004.4,
		"OffsetByCommissionAmount": 0,
		"OperateTime": "2024-05-21T11:28:53",
		"PayerPayeeName": "ToleranceOffset",
		"PayerPayeeType": "IndiCustomer",
		"PaymentMethod": "100",
		"PeriodEndDate": "2024-05-22",
		"PeriodStartDate": "2024-05-22",
		"RefFeeId": 874333534,
		"Tax": 74.4,
		"TotalPeriods": 1,
		"Transaction": {
			"@pk": 874333533,
			"@type": "BcpBizTransaction-BizTransaction",
			"BizModule": "10",
			"BizSource": "1",
			"BizTransId": 874333533,
			"BizTransTime": "2024-05-21T11:28:52",
			"BizTransType": "NEWBIZ",
			"BizUniqueId": "875450339",
			"BookingCurrencyCode": "USD",
			"BranchCode": "10002",
			"BranchName": "Brazil Branch",
			"BusinessObjectId": 1100002651370,
			"ChannelCode": "PTY10000001539007",
			"ChannelName": "Luna Test",
			"ChannelType": "14",
			"ChannelTypeName": "Agent Company",
			"CurrencyCode": "USD",
			"DirectBookingEr": 0.79,
			"DirectEr": 0.79,
			"HasMandate": "N",
			"LocalCurrencyCode": "BRL",
			"PaymentMethod": "100",
			"PaymentType": "1",
			"PolicyHolderName": "ToleranceOffset",
			"PolicyNo": "POTBTI00031232",
			"ProductCode": "TBTI",
			"ProductLineCode": "Travel",
			"ProductName": "API TEST",
			"RefTransId": 875450339,
			"RefTransNo": "POTBTI00031232",
			"TotalPeriods": 1
		},
		"VersionSeq": 1,
		"Selected": true
	}]
}
  
  ```
  
  Sample Response
  ```json
  {
    "Model": [{
        "@pk": 874333538,
        "@type": "BcpOffset-Offset",
        "Amount": 1004.4,
        "BookingCurrencyCode": "USD",
        "BusinessObjectId": 1100002652393,
        "CurrencyCode": "USD",
        "DetailList": [{
            "@pk": 874333539,
            "@type": "BcpOffsetDetail-OffsetDetail",
            "Amount": 1004.4,
            "BookingCurrencyCode": "USD",
            "BusinessObjectId": 1100002652469,
            "CurrencyCode": "USD",
            "DirectBookingEr": 1,
            "DirectEr": 1,
            "LocalCurrencyCode": "BRL",
            "OffsetDetailId": 874333539,
            "RefId": 874333535,
            "RefType": "3"
        }],
        "DirectBookingEr": 1,
        "DirectEr": 1,
        "HasNote": "N",
        "LocalCurrencyCode": "BRL",
        "OffsetBy": 10000000400001,
        "OffsetId": 874333538,
        "OffsetNo": "OFS20240500000009",
        "OffsetStatus": "1",
        "OffsetTime": "2024-05-21T03:28:56.251",
        "OffsetType": "3",
        "VersionSeq": 1
    }],
    "Status": "OK"
}
  ```
### Internal Data Behavior

The business model involved in the tolerance offset operation has the following relationships:

1.	Generate new offset records, among which the amounts of `BcpOffset` and `BcpOffsetDetail` are equal to the offset amounts filled in the UI.  
2.	Update the ARAP information selected by the UI. The updated balance equals the balance minus the offset amount filled in the UI. When the balance is 0, the status is updated to **Settled**, or otherwise, it is **Outstanding**.

After completing the tolerance offset, it is necessary to transmit data back to the business party.

3.	Features to be implemented: 
* Asynchronous settlement operations (e.g. Bank Charge)
* Commission dividends for multiple sale channels

## Reverse Offset API
### API Path
/bcp-core/offset/v1/reverseOffset

### Business Usage
Reverse the Offset transaction.

### API Sample
 Sample Request
  ```json
  [
    "10181390025,ABD707A2C6077777F677D607DE5095AF"
 ]
  ```
  
  Sample Response
  ```json
  {
    "Model": [
        {
            "@pk": 10181400015,
            "@type": "BcpReverse-Reverse",
            "BusinessObjectId": 1100002652882,
            "HasNote": "N",
            "RefId": "10181390025,ABD707A2C6077777F677D607DE5095AF",
            "ReverseBy": 10000001178005,
            "ReverseId": 10181400015,
            "ReverseReason": "manual",
            "ReverseTime": "2024-03-22T15:47:30",
            "ReverseType": "3"
        }
    ],
    "Status": "OK"
}
  ```
### Internal Data Behavior
Reverse Application and Offset is the reverse operation of Application. The business code contains Part 1 and 2 of the reverse collection. For business models and models associations, see Part 1 and 2 of the reverse collection.  

### What You Can Extend
After completing the reverse application, see BcpBffResourceRestful.java method：reverseOffset() for custom business operations in the bcp-bff-app code.

## How to handle BCPFee

BCP Fee are records of fee change during arap operations in the BCP system. Whenever there is a change in the amount of arap, corresponding BCP Fee data will be generated. This chapter introduces the changes in Fee during the offset operation process.

There are two sets of fee offset logics in the offset: proportional offset and priority offset, with the priority offset taking precedence over the proportional offset.

Premise: The fee types mentioned below refer to other fee types excluding installment payment fees, such as Premium-Direct Business, taxes, commission fees, Coverage A premiums, Coverage B premiums, etc. In each operation, the installment payment offset fee generated will be equal to the amount paid.

Propotional offset: Calculate the proportion of the current payment amount in the current installment amount, and offset the amounts of other Fee Types based on this proportion. Here is a example to illustrate.

<table>
<tr><td colSpan = "5"> The first installment is 120, and the second is 180.5. </td></tr>

<tr>
<th>Fee Type</th>
<th>Original Fee</th>
<th>Offset Ratio</th>
<th>First Offset Amount</th>
<th>Second Offset Amount</th>
</tr>

<tr>
<td>Installment Payable (arap)</td>
<td>300.5</td>
<td>120/300.5 = 0.3993</td>
<td>120</td>
<td>180.5</td>
</tr>

<tr>
<td>Premium-Direct Business</td>
<td>270.5</td>
<td>-</td>
<td>107.81 = 270.5*0.3993</td>
<td>162.69 = 270.5-107.81</td>
</tr>

<tr>
<td>Tax</td>
<td>30</td>
<td>-</td>
<td>11.98 = 30*0.3993</td>
<td>18.02 = 30-11.98</td>
</tr>

</table>

Priority offset: The priority of fee types is configured in the FeeTypePriority of the DataTable. During the offset process, fees are written off sequentially according to the cofigured priorities. Only after the amount of the highest priority fee type has been fully offset can the amount of the next priority fee type be wirtten off.

<table>
<tr><td colSpan = "2"> FeeType Priority Table </td></tr>

<tr>
<th>FeeType</th>
<th>Priority</th>
</tr>

<tr>
<td>Coverage A premium</td>
<td>1</td>
</tr>

<tr>
<td>Coverage B premium</td>
<td>2</td>
</tr>

<tr>
<td>Coverage C premium</td>
<td>3</td>
</tr>
</table>


<table>
<tr><td colSpan = "4"> The first installment is 120, and the second is 100. </td></tr>

<tr>
<th>Fee Type</th>
<th>Original Fee</th>
<th>First Offset Amount</th>
<th>Second Offset Amount</th>
</tr>
<tr>
<td>Installment Payable (arap)</td>
<td>300.5</td>
<td>120</td>
<td>100</td>
</tr>
<tr>
<td>Coverage A premium</td>
<td>150</td>
<td>120</td>
<td>30</td>
</tr>
<tr>
<td>Coverage B premium</td>
<td>30.5</td>
<td>0</td>
<td>30.5</td>
</tr>
<tr>
<td>Coverage C premium</td>
<td>120</td>
<td>0</td>
<td>39.5</td>
</tr>
</table>


The priority offset takes precedence over the proportional offset. If the priority of fee types is configured in the FeeTypePriority of the DataTable, the fees will be offset according to the priority-based method. If no priority is configured for the FeeType, the fees will be offset proportionally. In cases where some fees have configured priorities in the priority configuration table while others do not, the fees with configured priorities will be offset first according to their priority levels. If there is any remaining amount after offsetting the prioritized fees, the remaining fees will be offset proportionally. For example, in an offset involving five fee types, if two fee types have configured priorities in the FeeTypePriority and three do not, the two prioritized fee types will be offset first. If there is still an unoffset amount after this, the remaining three fees will be offset proportionally.

<table>
<tr><td colSpan = "2"> FeeType Priority Table </td></tr>
<tr>
<th>FeeType</th>
<th>Priority</th>
</tr>
<tr>
<td>Coverage A premium</td>
<td>1</td>
</tr>
</table>


<table>
<tr><td colSpan = "5"> The first installment is 120, the second is 100, and the third is 80.5. </td></tr>

<tr>
<th>Fee Type</th>
<th>Original Fee</th>
<th>First Offset Amount</th>
<th>Second Offset Amount</th>
<th>Third Offset Amount</th>
</tr>

<tr>
<td>Installment Payable (arap)</td>
<td>300.5</td>
<td>120</td>
<td>100</td>
<td>80.5</td>
</tr>

<tr>
<td>Coverage A premium</td>
<td>150</td>
<td>120</td>
<td>30</td>
<td>0</td>
</tr>

<tr>
<td>Coverage B premium</td>
<td>30.5</td>
<td>0</td>
<td>14.19 = (100-30)*(30.5/(30.5+120))</td>
<td>16.31 = 30.5-14.19</td>
</tr>

<tr>
<td>Coverage C premium</td>
<td>120</td>
<td>0</td>
<td>55.81 = (100-30)*(120/(30.5+120))</td>
<td>64.19 = 120-55.81</td>
</tr>

</table>
