Commit e8574337 authored by Viacheslav Sukhovieiev's avatar Viacheslav Sukhovieiev
Browse files

feat(CSD): update dutchStepPersent logic

parent 636acfa5
......@@ -994,24 +994,41 @@ schemas:
x-legalNameEn: Other requirements and additional information
minimalStep:
default: {}
description: |
Крок аукціону складає 1% чи 0.1% від стартової ціни, в залежності від
встановленного поля dutchStepPercent
allOf:
- $ref: '#/components/schemas/base.DutchMinimalStep'
x-legalNameUa: Розмір кроку аукціону
x-legalNameEn: Minimal step
dutchStep:
default: {}
description: |
Поле dutchStepValue автогенеруються на рівні ЦБД, без можливості внесення змін Організатором <br>
Для полів dutchStepQuantity та dutchStepPercent ЦБД формує дефолтне значення згідно процедури, Організатор має можливість змінити дефолтне значення.
Для поля dutchStepPercent Організатор має можливість обрати значення з [1, 0.1]
x-baseClass: 'prozorro_sale.procedure.packages.commercialSell.procedure.DutchStep'
allOf:
- $ref: '#/components/schemas/base.DutchStep'
- type: object
properties:
dutchStepQuantity:
type: integer
format: int64
maximum: 99
default: 99
minimum: 1
x-legalNameUa: Кількість кроків
x-legalNameEn: Dutch steps quantity
dutchStepPercent:
type: number
format: float
default: 1
enum:
- 1
- 0.1
x-legalNameUa: Відсоток зниження, %
x-legalNameEn: Percentage reduction, %
dutchStepValue:
description: автогеровано, розраховується як 1 % чи 0.1 % від стартової ціни
type: object
readOnly: true
allOf:
- $ref: '#/components/schemas/base.Value'
x-legalNameUa: Розмір кроку голландського раунду, грн
x-legalNameEn: Dutch step value
x-legalNameUa: Розмір кроку аукціону
x-legalNameEn: Minimal step
value:
......
......@@ -189,22 +189,27 @@ class DutchStepMixin:
"""
return cls.fields['dutchStep'].model_class
def _on_value_set(self, value):
"""Hook is called when value field is set
def check_dutch_step(self):
"""
Sets or updates dutchStep fields depending on
procedure value fields changing
"""
if self.dutchStep:
if self.value:
self.dutchStep.dutchStepValue = self.DutchStep.DutchStepValue({
'amount': round((self.value.to_primitive()['amount'] * self.dutchStep.dutchStepPercent) / 100, 2),
'currency': self.value.currency,
})
Args:
value (Value): value object
def check_minimal_step(self):
"""
Sets or updates minimalStep value depending on
procedure value and dutchStep fields changing
"""
if not value:
return
if self.minimalStep:
self.minimalStep.amount = value.amount // 100
self.minimalStep.currency = value.currency
if self.dutchStep:
self.dutchStep.dutchStepValue = self.DutchStep.DutchStepValue({
'amount': round((value.to_primitive()['amount'] * self.dutchStep.dutchStepPercent) / 100, 2),
'currency': value.currency,
})
if self.value and self.dutchStep:
self.minimalStep.amount = self.value.amount * self.dutchStep.dutchStepPercent // 100
self.minimalStep.currency = self.value.currency
def _validate_bid_value_amount(self, amount):
"""Method for validating bid.value.amount
......@@ -213,3 +218,11 @@ class DutchStepMixin:
amount (int): amount value
"""
pass
def _validate_data(self, raw_data, **kwargs):
super()._validate_data(raw_data, **kwargs)
if raw_data.get('dutchStep') or raw_data.get('value'):
self.check_dutch_step()
if raw_data.get('minimalStep') or raw_data.get('dutchStep') \
or raw_data.get('value'):
self.check_minimal_step()
......@@ -138,6 +138,40 @@ class BankAccountsByType(base.BankAccountsByType):
}
class DutchStep(base.DutchStep):
class Options:
override = True
import_roles = {
'owner': blacklist('dutchStepValue')
}
roles = {
'public': blacklist(''),
'owner': blacklist(''),
'bidder': blacklist('')
}
def check_dutch_step_quantity(self):
"""
Method checks DutchStep quantity according to
setted dutchStepPercent value
"""
if self.dutchStepPercent == 1:
if not self.dutchStepQuantity:
self.dutchStepQuantity = 99
elif self.dutchStepQuantity > 99:
raise DataError({'dutchStepQuantity': 'Value must be from 1 to 99'})
elif self.dutchStepPercent == 0.1:
if not self.dutchStepQuantity:
self.dutchStepQuantity = 999
elif self.dutchStepQuantity > 999:
raise DataError({'dutchStepQuantity': 'Value must be from 1 to 999'})
def _validate_data(self, raw_data, **kwargs):
self.check_dutch_step_quantity()
super()._validate_data(raw_data, **kwargs)
class _BaseProcedure(BankAccountsValidationMixin, base.Procedure, StateMachine):
CONTRACT_ACTIVATE_FIELDS = {
'dateSigned',
......
......@@ -41,6 +41,85 @@ class TestProcedureRectification(RectificationTest):
assert proc.minimalStep.amount == proc.value.amount // 100
assert proc.dutchStep.dutchStepValue.amount == proc.value.amount / 100
def test_procedure_minimalStep(self, make_procedure, acl_context):
proc = make_procedure()
assert proc.minimalStep.amount == proc.value.amount // 100
assert proc.minimalStep.currency == proc.value.currency
proc.update_procedure({
"minimalStep": {
"valueAddedTaxIncluded": True
}
}, acl_context(proc))
assert proc.minimalStep.amount == proc.value.amount // 100
assert proc.minimalStep.currency == proc.value.currency
proc.update_procedure({
"dutchStep": {
"dutchStepPercent": 0.1
}
}, acl_context(proc))
assert proc.minimalStep.amount == proc.value.amount // 1000
assert proc.minimalStep.currency == proc.value.currency
@pytest.mark.parametrize(('perc_val_1, quant_val_1, perc_val_2, quant_val_2'), [
(1, 99, 0.1, 999),
(0.1, 999, 1, 99),
])
def test_procedure_dutchStepQuantity_autogeneration(self, make_procedure, perc_val_1,
quant_val_1, perc_val_2,
quant_val_2, acl_context):
dutch_step = {
"dutchStepPercent": perc_val_1
}
proc = make_procedure(value_amount=20, dutchStep=dutch_step)
assert proc.dutchStep.dutchStepQuantity == quant_val_1
assert proc.dutchStep.dutchStepValue.amount == proc.value.amount / 100 * perc_val_1
proc.update_procedure({
"dutchStep": {
"dutchStepPercent": perc_val_2
}
}, acl_context(proc))
assert proc.dutchStep.dutchStepQuantity == quant_val_2
assert proc.dutchStep.dutchStepValue.amount == proc.value.amount / 100 * perc_val_2
@pytest.mark.parametrize(('percent_value, quantity_value, expected'), [
(1, 1, does_not_raise()),
(1, 99, does_not_raise()),
(1, 100, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepQuantity": '
r'"Value must be from 1 to 99"\}\}$'),),
(1, 0, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepQuantity": '
r'\["Int value should be greater than or equal to 1."\]\}\}$'),),
(2, 99, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepPercent": '
r'\["Value must be one of \[1, 0.1\]."\]\}\}$'),),
(0.1, 1, does_not_raise()),
(0.1, 999, does_not_raise()),
(0.1, 1000, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepQuantity": '
r'"Value must be from 1 to 999"\}\}$'),),
(0.2, 999, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepPercent": '
r'\["Value must be one of \[1, 0.1\]."\]\}\}$'),),
(0, 99, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepPercent": '
r'\["Value must be one of \[1, 0.1\]."\]\}\}$'),),
(0, 999, pytest.raises(errors.DataError, match=r'^\{"dutchStep": \{"dutchStepPercent": '
r'\["Value must be one of \[1, 0.1\]."\]\}\}$'),),
])
def test_procedure_dutchStepPercent_dutchStepQuantity_validation(self, percent_value, quantity_value,
expected, make_procedure, acl_context):
dutch_step = {
"dutchStepPercent": percent_value,
"dutchStepQuantity": quantity_value,
}
with expected:
make_procedure(dutchStep=dutch_step)
@pytest.mark.parametrize(('data', 'expected'), [
pytest.param(
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment