buildCumulativeResult method
PaymentResult
buildCumulativeResult({})
Builds a cumulative PaymentResult summarising the entire split session.
The result includes the total amount paid across all successful legs, the split tip amount, and the payment leg count.
Implementation
PaymentResult buildCumulativeResult({
required String businessId,
required String userId,
required String merchantId,
String isoCurrencyCode = '',
String shortCurrencyCode = '',
}) {
if (_currentSession == null) {
_logger?.error(this, 'buildCumulativeResult: no active session');
throw StateError(
'Cannot build cumulative result: no active split session.',
);
}
final session = _currentSession!;
final totalPaid = session.amountPaid;
// Calculate change and tendered amounts for split flows.
//
// Change = sum of per-cash-leg surplus (cashTendered − legAmount) across
// all successful cash legs where cashTendered > legAmount.
// This is the surplus (excluding the implicit tip baked into the
// KeypadPage amount) that was accumulated from cash overpayment.
//
// amountTendered = totalPaid + totalCashSurplus — represents what was
// actually tendered, including the tip amount plus the cash surplus.
final successfulLegs = session.paymentLegs.where((l) => l.isSuccess);
Decimal totalCashSurplus = Decimal.zero;
for (final leg in successfulLegs) {
if (leg.cashTendered != null && leg.cashTendered! > leg.amount) {
totalCashSurplus += leg.cashTendered! - leg.amount;
}
}
final change = totalCashSurplus;
final amountTendered = totalPaid + totalCashSurplus;
_logger?.info(
this,
'buildCumulativeResult: building — '
'state=${session.state.name}, '
'amountPaid=$totalPaid, '
'tipAmount=${session.tipAmount}, '
'changeAmount=$change, '
'amountTendered=$amountTendered, '
'totalCashSurplus=$totalCashSurplus, '
'successfulLegs=${session.successfulLegCount}/'
'${session.paymentLegs.length}',
);
return PaymentResult(
businessId: businessId,
userId: userId,
transactionId: session.splitId,
transactionReference: 'SPLIT-${session.splitId}',
traceId: session.splitId,
transactionType: TransactionType.purchase,
amount: session.amountPaid,
isoCurrencyCode: isoCurrencyCode,
shortCurrencyCode: shortCurrencyCode,
transactionStatus: PaymentStatus.processed,
status: session.state == SplitSessionState.fullyPaid
? 'success'
: 'partial_success',
statusCode: session.state == SplitSessionState.fullyPaid
? 'FULLY_PAID'
: 'PARTIALLY_PAID',
statusMessage: session.state == SplitSessionState.fullyPaid
? 'Split payment completed'
: 'Split payment partially completed',
statusDescription: session.state == SplitSessionState.fullyPaid
? 'All payment legs processed successfully'
: '${session.successfulLegCount} of ${session.paymentLegs.length} legs processed',
batchReference: '',
batchNumber: 0,
paymentType: 'split',
paymentProviderId: '',
paymentProviderType: PaymentProviderType.unknown,
paymentProviderName: 'Split Payment',
merchantId: merchantId,
authCode: '',
authResponseCode: '',
authResponse: '',
entry: '',
entryMode: '',
paymentMethod: 'split',
maskedPan: '',
uti: '',
terminalId: '',
otherAmount: Decimal.zero,
splitTipAmount: session.totalTipAmount,
splitExplicitTipAmount: session.explicitTipAmount,
paymentLegCount: session.successfulLegCount,
changeAmount: change,
amountTendered: amountTendered,
);
}