Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a407828329451172 calculation of client payments #61

47 changes: 47 additions & 0 deletions openprocurement/tender/esco/npv_calculation.py
Expand Up @@ -46,6 +46,53 @@ def calculate_discount_rates(
]


def calculate_payment(
yearly_payments_percentage,
client_cost_reduction,
days_with_payments,
days_for_discount_rate):
'''Calculates client payment to a participant'''

if days_with_payments > 0:
# Transormation Fraction(str(float)) is done because of its
# better precision than Fraction(float).
#
# For example:
# >>> Fraction(str(0.2))
# Fraction(1, 5)
# >>> Fraction(0.2)
# Fraction(3602879701896397, 18014398509481984)

yearly_payments_percentage = Fraction(
Fraction(str(yearly_payments_percentage)),
100
)
client_cost_reduction = Fraction(str(client_cost_reduction))

return (yearly_payments_percentage * client_cost_reduction *
Fraction(days_with_payments, days_for_discount_rate))
return 0


def calculate_payments(
yearly_payments_percentage,
client_cost_reductions,
days_with_payments,
days_for_discount_rate):
'''Calculates client payments to a participant'''

lists = zip(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

а може ще якось і без зіпу?)

Copy link
Contributor Author

@Tuoris Tuoris Aug 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ні)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

та ні, зроби таки без використання зіпу.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

client_cost_reductions,
days_with_payments,
days_for_discount_rate,
)

return [
calculate_payment(yearly_payments_percentage, *arg)
for arg in lists
]


def calculate_days_with_cost_reduction(
announcement_date,
days_per_year=DAYS_PER_YEAR,
Expand Down
4 changes: 4 additions & 0 deletions openprocurement/tender/esco/tests/npv.py
Expand Up @@ -5,6 +5,8 @@
contract_duration,
discount_rate,
discount_rates,
client_payment,
client_payments,
days_with_cost_reduction,
)

Expand All @@ -18,6 +20,8 @@ class NPVCalculationTest(unittest.TestCase):
test_contract_duration = snitch(contract_duration)
test_discount_rate = snitch(discount_rate)
test_discount_rates = snitch(discount_rates)
test_client_payment = snitch(client_payment)
test_client_payments = snitch(client_payments)
test_days_with_cost_reduction = snitch(days_with_cost_reduction)


Expand Down
123 changes: 122 additions & 1 deletion openprocurement/tender/esco/tests/npv_blanks.py
@@ -1,10 +1,17 @@
from datetime import date
from openprocurement.tender.esco.tests.npv_test_data import DISCOUNT_COEF, DISCOUNT_RATE
from openprocurement.tender.esco.tests.npv_test_data import (
DISCOUNT_COEF,
DISCOUNT_RATE,
CLIENT_PAYMENT_DATA,
CLIENT_PAYMENTS_DATA,
)
from openprocurement.tender.esco.constants import DAYS_PER_YEAR, NPV_CALCULATION_DURATION
from openprocurement.tender.esco.npv_calculation import (
calculate_contract_duration,
calculate_discount_rate,
calculate_discount_rates,
calculate_payment,
calculate_payments,
calculate_discount_coef,
calculate_days_with_cost_reduction,
)
Expand Down Expand Up @@ -120,6 +127,120 @@ def discount_rates(self):
self.assertEqual(calculated_rates[-1], predefined_rate2)


def client_payment(self):

# Predefined values
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

винеси тестові дані в окремий файл

yearly_payments_percentage = CLIENT_PAYMENT_DATA['yearly_percentage']
client_cost_reduction = CLIENT_PAYMENT_DATA['client_cost_reduction']
days_with_payments = CLIENT_PAYMENT_DATA['days_with_payments']
days_for_discount_rate = CLIENT_PAYMENT_DATA['days_for_discount_rate']
payment_predefined = CLIENT_PAYMENT_DATA['payment']
prec = 2

payment = calculate_payment(
yearly_payments_percentage,
client_cost_reduction,
days_with_payments,
days_for_discount_rate,
)

self.assertEqual(round(payment, prec), round(payment_predefined, prec))
self.assertEqual(
round(yearly_payments_percentage * client_cost_reduction / 100, prec),
round(payment_predefined, prec),
)

# No days for payments at all
days_with_payments = 0
payment = calculate_payment(
yearly_payments_percentage,
client_cost_reduction,
days_with_payments,
days_for_discount_rate,
)
self.assertEqual(payment, 0)

# If there is more days for payments than payment must be greater
last_payment = payment
days_with_payments += 1
payment = calculate_payment(
yearly_payments_percentage,
client_cost_reduction,
days_with_payments,
days_for_discount_rate,
)
self.assertGreater(payment, last_payment)

# If there is less days for payments than payment must be smaller
last_payment = payment
days_with_payments -= 10
payment = calculate_payment(
yearly_payments_percentage,
client_cost_reduction,
days_with_payments,
days_for_discount_rate,
)
self.assertLess(payment, last_payment)


def client_payments(self):

periods = 21

# Predefined values
yearly_payments_percentage = CLIENT_PAYMENTS_DATA['yearly_percentage']
client_cost_reductions = CLIENT_PAYMENTS_DATA['client_cost_reductions']
days_with_payments = CLIENT_PAYMENTS_DATA['days_with_payments']
days_for_discount_rate = CLIENT_PAYMENTS_DATA['days_for_discount_rate']
payments_predefined = CLIENT_PAYMENTS_DATA['payments']
payments_sum = CLIENT_PAYMENTS_DATA['payments_sum']
prec = 2

payments = calculate_payments(
yearly_payments_percentage,
client_cost_reductions,
days_with_payments,
days_for_discount_rate,
)
self.assertEqual(len(payments), len(client_cost_reductions))
for i, _ in enumerate(payments):
self.assertEqual(
round(payments[i], prec),
round(payments_predefined[i], prec)
)

self.assertEqual(round(sum(payments), prec), round(payments_sum, prec))

# No days for payments at all
days_with_payments = CLIENT_PAYMENTS_DATA['days_no_payments']
days_for_discount_rate = CLIENT_PAYMENTS_DATA['full_years_discount']
payments = calculate_payments(
yearly_payments_percentage,
client_cost_reductions,
days_with_payments,
days_for_discount_rate,
)
self.assertEqual(len(payments), len(client_cost_reductions))
for payment in payments:
self.assertEqual(payment, 0)

# If there is more days for payments than payment must be greater
# days_with_payments = [10, 20, ...]
days_with_payments = CLIENT_PAYMENTS_DATA['growing_days_with_payments']
payments = calculate_payments(
yearly_payments_percentage,
client_cost_reductions,
days_with_payments,
days_for_discount_rate,
)
self.assertEqual(len(payments), len(client_cost_reductions))
for i, _ in enumerate(payments[:-1]):
self.assertLess(
payments[i],
payments[i + 1],
)


def days_with_cost_reduction(self):
announcement_date = date(2017, 8, 18)
self.assertEqual(
Expand Down
21 changes: 21 additions & 0 deletions openprocurement/tender/esco/tests/npv_test_data.py
Expand Up @@ -28,3 +28,24 @@
'second_test': [Fraction(str(0))]*21,
'third_test': [Fraction(str(0.12500))] * 21
}

CLIENT_PAYMENT_DATA = {
'yearly_percentage': 70,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

подавай відсоток у вигляді 0.7, потрібно переробити під це логіку

'client_cost_reduction': 92.47,
'days_with_payments': 135,
'days_for_discount_rate': 135,
'payment': 64.73,
}

CLIENT_PAYMENTS_DATA = {
'yearly_percentage': 70.0,
'client_cost_reductions': [92.47] + [250.00] * 20,
'days_with_payments': [135, 365, 365, 230] + [0] * (21 - 4),
'days_for_discount_rate': [135, 365, 365, 365] + [0] * (21 - 4),
'payments':
[64.73, 175.00, 175.00, 110.27] + [0] * (21 - 4),
'payments_sum': 525.00,
'days_no_payments': [0] * 21,
'full_years_discount': [365] * 21,
'growing_days_with_payments': [(i + 1) * 10 for i in range(21)],
}