mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Cool idea: Make Loan.NextDueDate optional; clear it when complete
- Check "simple" loanMakePayment failure conditions early
This commit is contained in:
@@ -562,7 +562,7 @@ LEDGER_ENTRY(ltLOAN, 0x0089, Loan, loan, ({
|
|||||||
{sfGracePeriod, soeREQUIRED},
|
{sfGracePeriod, soeREQUIRED},
|
||||||
{sfPeriodicPayment, soeREQUIRED},
|
{sfPeriodicPayment, soeREQUIRED},
|
||||||
{sfPreviousPaymentDate, soeDEFAULT},
|
{sfPreviousPaymentDate, soeDEFAULT},
|
||||||
{sfNextPaymentDueDate, soeREQUIRED},
|
{sfNextPaymentDueDate, soeOPTIONAL},
|
||||||
{sfPaymentRemaining, soeDEFAULT},
|
{sfPaymentRemaining, soeDEFAULT},
|
||||||
{sfPrincipalOutstanding, soeDEFAULT},
|
{sfPrincipalOutstanding, soeDEFAULT},
|
||||||
{sfTotalValueOutstanding, soeDEFAULT},
|
{sfTotalValueOutstanding, soeDEFAULT},
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ struct PaymentComponentsPlus : public PaymentComponents
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class NumberProxy, class Int32Proxy>
|
template <class NumberProxy, class Int32Proxy, class Int32OptionalProxy>
|
||||||
LoanPaymentParts
|
LoanPaymentParts
|
||||||
doPayment(
|
doPayment(
|
||||||
PaymentComponentsPlus const& payment,
|
PaymentComponentsPlus const& payment,
|
||||||
@@ -263,9 +263,13 @@ doPayment(
|
|||||||
NumberProxy& referencePrincipalProxy,
|
NumberProxy& referencePrincipalProxy,
|
||||||
Int32Proxy& paymentRemainingProxy,
|
Int32Proxy& paymentRemainingProxy,
|
||||||
Int32Proxy& prevPaymentDateProxy,
|
Int32Proxy& prevPaymentDateProxy,
|
||||||
Int32Proxy& nextDueDateProxy,
|
Int32OptionalProxy& nextDueDateProxy,
|
||||||
std::uint32_t paymentInterval)
|
std::uint32_t paymentInterval)
|
||||||
{
|
{
|
||||||
|
XRPL_ASSERT_PARTS(
|
||||||
|
nextDueDateProxy,
|
||||||
|
"ripple::detail::doPayment",
|
||||||
|
"Next due date proxy set");
|
||||||
if (payment.final)
|
if (payment.final)
|
||||||
{
|
{
|
||||||
paymentRemainingProxy = 0;
|
paymentRemainingProxy = 0;
|
||||||
@@ -283,16 +287,19 @@ doPayment(
|
|||||||
"ripple::detail::doPayment",
|
"ripple::detail::doPayment",
|
||||||
"Full value payment");
|
"Full value payment");
|
||||||
|
|
||||||
prevPaymentDateProxy = nextDueDateProxy;
|
prevPaymentDateProxy = *nextDueDateProxy;
|
||||||
// May as well...
|
// Remove the field. This is the only condition where nextDueDate is
|
||||||
nextDueDateProxy = 0;
|
// allowed to be removed.
|
||||||
|
nextDueDateProxy = std::nullopt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paymentRemainingProxy -= 1;
|
paymentRemainingProxy -= 1;
|
||||||
|
|
||||||
prevPaymentDateProxy = nextDueDateProxy;
|
prevPaymentDateProxy = *nextDueDateProxy;
|
||||||
nextDueDateProxy += paymentInterval;
|
// STObject::OptionalField does not define operator+=, and I don't want
|
||||||
|
// to add one right now.
|
||||||
|
nextDueDateProxy = *nextDueDateProxy + paymentInterval;
|
||||||
}
|
}
|
||||||
// A single payment always pays the same amount of principal. Only the
|
// A single payment always pays the same amount of principal. Only the
|
||||||
// interest and fees are extra for a late payment
|
// interest and fees are extra for a late payment
|
||||||
@@ -321,21 +328,21 @@ doPayment(
|
|||||||
* labeled "the payment is late"
|
* labeled "the payment is late"
|
||||||
* * section 3.2.4.1.2 (Late Payment)
|
* * section 3.2.4.1.2 (Late Payment)
|
||||||
*/
|
*/
|
||||||
template <AssetType A, class NumberProxy, class Int32Proxy>
|
template <AssetType A>
|
||||||
Expected<PaymentComponentsPlus, TER>
|
Expected<PaymentComponentsPlus, TER>
|
||||||
handleLatePayment(
|
handleLatePayment(
|
||||||
A const& asset,
|
A const& asset,
|
||||||
ApplyView& view,
|
ApplyView const& view,
|
||||||
NumberProxy& principalOutstandingProxy,
|
Number const& principalOutstanding,
|
||||||
Int32Proxy& nextDueDateProxy,
|
std::int32_t nextDueDate,
|
||||||
PaymentComponentsPlus const& periodic,
|
PaymentComponentsPlus const& periodic,
|
||||||
TenthBips32 const lateInterestRate,
|
TenthBips32 lateInterestRate,
|
||||||
std::int32_t loanScale,
|
std::int32_t loanScale,
|
||||||
Number const& latePaymentFee,
|
Number const& latePaymentFee,
|
||||||
STAmount const& amount,
|
STAmount const& amount,
|
||||||
beast::Journal j)
|
beast::Journal j)
|
||||||
{
|
{
|
||||||
if (!hasExpired(view, nextDueDateProxy))
|
if (!hasExpired(view, nextDueDate))
|
||||||
return Unexpected(tesSUCCESS);
|
return Unexpected(tesSUCCESS);
|
||||||
|
|
||||||
// the payment is late
|
// the payment is late
|
||||||
@@ -343,10 +350,10 @@ handleLatePayment(
|
|||||||
// being late, as computed by 3.2.4.1.2.
|
// being late, as computed by 3.2.4.1.2.
|
||||||
auto const latePaymentInterest = loanLatePaymentInterest(
|
auto const latePaymentInterest = loanLatePaymentInterest(
|
||||||
asset,
|
asset,
|
||||||
principalOutstandingProxy,
|
principalOutstanding,
|
||||||
lateInterestRate,
|
lateInterestRate,
|
||||||
view.parentCloseTime(),
|
view.parentCloseTime(),
|
||||||
nextDueDateProxy,
|
nextDueDate,
|
||||||
loanScale);
|
loanScale);
|
||||||
XRPL_ASSERT(
|
XRPL_ASSERT(
|
||||||
latePaymentInterest >= 0,
|
latePaymentInterest >= 0,
|
||||||
@@ -770,10 +777,27 @@ loanMakePayment(
|
|||||||
* This function is an implementation of the XLS-66 spec,
|
* This function is an implementation of the XLS-66 spec,
|
||||||
* section 3.2.4.3 (Transaction Pseudo-code)
|
* section 3.2.4.3 (Transaction Pseudo-code)
|
||||||
*/
|
*/
|
||||||
|
auto principalOutstandingProxy = loan->at(sfPrincipalOutstanding);
|
||||||
|
auto paymentRemainingProxy = loan->at(sfPaymentRemaining);
|
||||||
|
|
||||||
|
if (paymentRemainingProxy == 0 || principalOutstandingProxy == 0)
|
||||||
|
{
|
||||||
|
// Loan complete
|
||||||
|
JLOG(j.warn()) << "Loan is already paid off.";
|
||||||
|
return Unexpected(tecKILLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next payment due date must be set unless the loan is complete
|
||||||
|
auto nextDueDateProxy = loan->at(~sfNextPaymentDueDate);
|
||||||
|
if (!nextDueDateProxy)
|
||||||
|
{
|
||||||
|
JLOG(j.warn()) << "Loan next payment due date is not set.";
|
||||||
|
return Unexpected(tecINTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
std::int32_t const loanScale = loan->at(sfLoanScale);
|
std::int32_t const loanScale = loan->at(sfLoanScale);
|
||||||
auto totalValueOutstandingProxy = loan->at(sfTotalValueOutstanding);
|
auto totalValueOutstandingProxy = loan->at(sfTotalValueOutstanding);
|
||||||
auto interestOwedProxy = loan->at(sfInterestOwed);
|
auto interestOwedProxy = loan->at(sfInterestOwed);
|
||||||
auto principalOutstandingProxy = loan->at(sfPrincipalOutstanding);
|
|
||||||
auto referencePrincipalProxy = loan->at(sfReferencePrincipal);
|
auto referencePrincipalProxy = loan->at(sfReferencePrincipal);
|
||||||
bool const allowOverpayment = loan->isFlag(lsfLoanOverpayment);
|
bool const allowOverpayment = loan->isFlag(lsfLoanOverpayment);
|
||||||
|
|
||||||
@@ -790,18 +814,9 @@ loanMakePayment(
|
|||||||
TenthBips32 const overpaymentFee{loan->at(sfOverpaymentFee)};
|
TenthBips32 const overpaymentFee{loan->at(sfOverpaymentFee)};
|
||||||
|
|
||||||
auto const periodicPayment = loan->at(sfPeriodicPayment);
|
auto const periodicPayment = loan->at(sfPeriodicPayment);
|
||||||
auto paymentRemainingProxy = loan->at(sfPaymentRemaining);
|
|
||||||
|
|
||||||
auto prevPaymentDateProxy = loan->at(sfPreviousPaymentDate);
|
auto prevPaymentDateProxy = loan->at(sfPreviousPaymentDate);
|
||||||
std::uint32_t const startDate = loan->at(sfStartDate);
|
std::uint32_t const startDate = loan->at(sfStartDate);
|
||||||
auto nextDueDateProxy = loan->at(sfNextPaymentDueDate);
|
|
||||||
|
|
||||||
if (paymentRemainingProxy == 0 || principalOutstandingProxy == 0)
|
|
||||||
{
|
|
||||||
// Loan complete
|
|
||||||
JLOG(j.warn()) << "Loan is already paid off.";
|
|
||||||
return Unexpected(tecKILLED);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t const paymentInterval = loan->at(sfPaymentInterval);
|
std::uint32_t const paymentInterval = loan->at(sfPaymentInterval);
|
||||||
// Compute the normal periodic rate, payment, etc.
|
// Compute the normal periodic rate, payment, etc.
|
||||||
@@ -840,7 +855,7 @@ loanMakePayment(
|
|||||||
asset,
|
asset,
|
||||||
view,
|
view,
|
||||||
principalOutstandingProxy,
|
principalOutstandingProxy,
|
||||||
nextDueDateProxy,
|
*nextDueDateProxy,
|
||||||
periodic,
|
periodic,
|
||||||
lateInterestRate,
|
lateInterestRate,
|
||||||
loanScale,
|
loanScale,
|
||||||
|
|||||||
Reference in New Issue
Block a user