Price calculations
This document provides an overview of how various transaction amount fields in a TransactionItem are calculated and influenced. Additionally, it provides details on how totalBalance is calculated for Checkout and Order entities.
Transaction Amount Fields Overviewβ
The following fields are calculated based on transaction events and their types:
authorizedAmount: The total amount successfully authorized.chargedAmount: The total amount successfully charged.refundedAmount: The total amount successfully refunded.canceledAmount: The total amount successfully canceled.authorizePendingAmount: The total amount of pending authorizations.chargePendingAmount: The total amount of pending charges.refundPendingAmount: The total amount of pending refunds.cancelPendingAmount: The total amount of pending cancellations.
Calculation processβ
When the transaction amounts are recalculated, firstly all values are set to zero, then the calculations are applied in the following order:
- recalculate amounts based on events without PSP reference
- recalculate amounts based on
AUTHORIZATIONevents - recalculate amounts based on
CHARGEevents - recalculate amounts based on
REFUNDevents - recalculate amounts based on
CANCELevents At each step, the amounts are incrementally adjusted by adding or subtracting values calculated in the current step to the totals from the previous step.
Assumptionsβ
1. Event Grouping:β
- Events are grouped based on their PSP reference and type of action (e.g., authorization, charge).
- Grouping ensures that events of the same type and PSP reference are properly matched to calculate amounts accurately.
2. Pending Amounts:β
- Pending amounts (
authorizePendingAmount,chargePendingAmount,refundPendingAmount,cancelPendingAmount) are increased only if aREQUESTevent exists for the corresponding PSP reference. - If a success or failure event is also associated with the same PSP reference, the system assumes the requested amount has already been processed, and the pending amount will not be increased.
3. SUCCESS and FAILURE Events:β
- The transaction amount (e.g.,
authorizedAmount,chargedAmount) is increased only when aSUCCESSevent exists. - If both a
SUCCESSandFAILUREevent are present for the same PSP reference, the system compares their creation timestamps:- If the
FAILUREevent is newer, theSUCCESSevent is ignored. - If the
SUCCESSevent is newer, it is used for the calculations.
- If the
4. Events Without PSP References Resulting from TransactionCreate and TransactionUpdate:β
- Events without PSP references can result from using the
TransactionCreateorTransactionUpdatemutations. These events are automatically created to ensure accurate transaction amount calculations. The following events might lack a PSP reference:AUTHORIZATION_SUCCESSAUTHORIZATION_ADJUSTMENTCHARGE_SUCCESSCHARGE_BACKREFUND_SUCCESSREFUND_REVERSECANCEL_SUCCESS
5. Adjustment Events:β
- The
AUTHORIZATION_ADJUSTMENT, overrides previous amount from previousAUTHORIZATIONevents, this means that if an adjustment is present, older authorization events are ignored, and the adjusted amount becomes the new authorized value.
This logic ensures that transaction amounts reflect the current state of the transaction based on its event history while accounting for both processed and pending actions.
Calculation detailsβ
For events without pspReferenceβ
The events that lacks the pspReference resulting from TransactionCreate and TransactionUpdate mutations are influence the transaction amounts as follow:
AUTHORIZATION_SUCCESSincreasesauthorizedAmountby the event amountAUTHORIZATION_ADJUSTMENToverrides the existingauthorizedAmountby the even amountCHARGE_SUCCESSincreaseschargedAmountby the event amountCHARGE_BACKreduceschargedAmountby the event amountREFUND_SUCCESSincreasesrefundedAmountby the event amountREFUND_REVERSEincreaseschargedAmountby the event amountCANCEL_SUCCESSincreasescanceledAmountby the event amount
For events with pspReferenceβ
Events like X_REQUEST, generated by Saleor when calling the payment app, are excluded from calculations until a corresponding event with a valid psp_reference is received from the payment app.
For example, an AUTHORIZATION_REQUEST event will not affect the calculations until an AUTHORIZATION_SUCCESS or a similar event containing a psp_reference is returned by the payment app.
The following calculation rules apply to events that share the same pspReference.
Authorized Value (transactionItem.authorizedAmount)β
- GIVEN there is an
AUTHORIZATION_SUCCESSevent- WHEN there is no
AUTHORIZATION_FAILURE - OR WHEN the
AUTHORIZATION_FAILUREevent is older thanAUTHORIZATION_SUCCESS- THEN value increases by the
AUTHORIZATION_SUCCESSevent's amount.
- THEN value increases by the
- WHEN there is no
- GIVEN an
AUTHORIZATION_ADJUSTMENTevent- WHEN it's the latest event of this type
- THEN value is overwritten by the
AUTHORIZATION_ADJUSTMENTevent amount.
- THEN value is overwritten by the
- WHEN it's the latest event of this type
- GIVEN there is a
CHARGE_REQUESTorCHARGE_SUCCESSevent:- THEN value is reduced by the event's amount.
- GIVEN there is a
CANCEL_REQUESTorCANCEL_SUCCESSevent:- THEN value is reduced by the event's amount.
- GIVEN all calculations were performed and we have result
authorizationAmount- WHEN calculated
authorizationAmountis below0- THEN
authorizationAmountis set to0(it cannot be lower than 0)
- THEN
- WHEN calculated
Authorization Pending Value (transactionItem.authorizePendingAmount)β
- GIVEN there is an
AUTHORIZATION_REQUESTevent:- WHEN there is no
AUTHORIZATION_FAILUREorAUTHORIZATION_SUCCESS- THEN value increases by the
AUTHORIZATION_REQUESTevent's amount
- THEN value increases by the
- WHEN there is no
Charge Value (transactionItem.chargedAmount)β
- GIVEN there is a
CHARGE_SUCCESSevent- WHEN there is no
CHARGE_FAILURE - OR WHEN the
CHARGE_FAILUREevent is older thanCHARGE_SUCCESS- THEN value increases by the
CHARGE_SUCCESSevent's amount.
- THEN value increases by the
- WHEN there is no
- GIVEN there is a
CHARGE_BACKevent- THENvalue is reduced by the event's amount
- GIVEN there is a
REFUND_REQUESTorREFUND_SUCCESSevent:- THEN value is reduced by the event's amount.
- GIVEN there is a
REFUND_REVERSEevent:- THEN value is increased by the event's amount.
- This value can be negative.
Please note that chargedAmount is not affected by CANCEL events, as these are solely used for matching with AUTHORIZATION events.
Charge Pending Value (transactionItem.chargePendingAmount)β
- GIVEN there is a
CHARGE_REQUESTevent:- WHEN there is no
CHARGE_FAILUREorCHARGE_SUCCESS- THEN value increases by the
CHARGE_REQUESTevent's amount
- THEN value increases by the
- WHEN there is no
Refunded Value (transactionItem.refundedAmount)β
- GIVEN there is a
REFUND_SUCCESSevent- WHEN there is no
REFUND_FAILURE - OR WHEN the
REFUND_FAILUREevent is older thanREFUND_SUCCESS- THEN value increases by the
REFUND_SUCCESSevent's amount.
- THEN value increases by the
- WHEN there is no
- GIVEN there is a
REFUND_REVERSEevent:- THEN value is reduced by the event's amount.
CHARGE_BACK events, which behave similarly to refunds by reducing the chargedAmount, are not included in refundedAmount. This is because they are initiated by the issuing bank, not the merchant.
Refund Pending Value (transactionItem.refundPendingAmount)β
- GIVEN there is a
REFUND_REQUESTevent:- WHEN there is no
REFUND_FAILUREorREFUND_SUCCESS- THEN value increases by the
REFUND_REQUESTevent's amount
- THEN value increases by the
- WHEN there is no
Canceled Value (transactionItem.canceledAmount )β
- GIVEN there is a
CANCEL_SUCCESSevent- WHEN there is no
CANCEL_FAILURE - OR WHEN the
CANCEL_FAILUREevent is older thanCANCEL_SUCCESS- THEN value increases by the
CANCEL_SUCCESSevent's amount.
- THEN value increases by the
- WHEN there is no
Cancel Pending Value (transactionItem.cancelPendingAmount)β
- GIVEN there is a
CANCEL_REQUESTevent:- WHEN there is no
CANCEL_FAILUREorCANCEL_REQUEST- THEN value increases by the
CANCEL_REQUESTevent's amount
- THEN value increases by the
- WHEN there is no
Total Balance Calculationβ
The totalBalance represents the difference between the expected total cost and the total amount charged (including pending charges).
This balance indicates whether the customer has overpaid (positive balance) or underpaid (negative balance) for the order.
Below is an explanation of how totalBalance is computed.
Total balance for Checkout (checkout.totalBalance)β
For a Checkout, totalBalance reflects the remaining balance after considering the total checkout cost, charged amounts, and pending charges.
It is calculated as the difference between the sum of all successful and pending charges across associated transactions and the checkoutβs total price:
totalBalance = totalCharged - checkout.totalPrice
where:
totalCharged = (
sum(transaction.chargedAmount for transaction in transactions)
+ sum(transaction.chargePendingAmount for transaction in transactions)
)
Total balance for Order (order.totalBalance)β
For an Order, totalBalance represents the remaining balance after accounting for order.totalPrice, charged amounts, and granted refunds.
It is calculated as the difference between the total charged (including pending charges) and the order cost adjusted for granted refunds:
totalBalance = totalCharged - (order.totalPrice - totalGrantedRefund)
where totalCharged is sum of all successful and pending charges across associated transactions:
totalCharged = (
sum(transaction.amountCharged for transaction in transactions)
+ sum(transaction.amountChargePending for transaction in transactions)
)
and totalGrantedRefund is a total of all refunds issued to the customer:
totalGrantedRefund = sum(grantedRefund.amount for grantedRefund in grantedRefunds)