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

WIP: Add rectification period dgfOtherAssets #112

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Introduction
============

openprocurement.auctions.dgf repository contains code for Deposit Guarantee Fund auctions.
`openprocurement.auctions.dgf` repository contains code for Deposit Guarantee Fund auctions.

Documentation can be found here http://dgf.api-docs.openprocurement.org/uk/latest/

4 changes: 4 additions & 0 deletions openprocurement/auctions/dgf/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from datetime import timedelta


FINANCIAL_VIEW_LOCATIONS = [
"openprocurement.auctions.dgf.views.financial",
Expand All @@ -10,3 +12,5 @@

DEFAULT_PROCUREMENT_METHOD_TYPE_OTHER = "DGFOtherAssets"
DEFAULT_PROCUREMENT_METHOD_TYPE_FINANCIAL = "DGFFinancialAssets"

RECTIFICATION_PERIOD_DURATION = timedelta(days=2)
124 changes: 90 additions & 34 deletions openprocurement/auctions/dgf/models.py
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
# -*- coding: utf-8 -*-
from datetime import timedelta

from pyramid.security import Allow
from schematics.exceptions import ValidationError
from schematics.transforms import whitelist
from schematics.types import (
StringType,
IntType,
BooleanType,
DateType,
IntType,
MD5Type,
BooleanType
StringType,
)
from schematics.types.compound import ModelType
from schematics.types.serializable import serializable
from urlparse import urlparse, parse_qs
from string import hexdigits
from zope.interface import implementer

from openprocurement.auctions.core.constants import (
DGF_DECISION_REQUIRED_FROM,
DGF_ELIGIBILITY_CRITERIA,
DGF_ID_REQUIRED_FROM,
DGF_PLATFORM_LEGAL_DETAILS,
DGF_PLATFORM_LEGAL_DETAILS_FROM,
DGF_ID_REQUIRED_FROM,
DGF_DECISION_REQUIRED_FROM,
)
from openprocurement.auctions.core.includeme import IAwardingNextCheck
from openprocurement.auctions.core.models import (
ListType,
ComplaintModelType,
IAuction,
from openprocurement.auctions.core.models.schema import (
Auction as BaseAuction,
Bid as BaseBid,
dgfCancellation as Cancellation,
dgfItem as Item,
dgfDocument as Document,
dgfComplaint as Complaint,
ComplaintModelType,
Feature,
Period,
FinancialOrganization,
IAuction,
ListType,
Lot,
dgf_auction_roles,
Period,
RectificationPeriod,
calc_auction_end_time,
dgfCancellation as Cancellation,
dgfComplaint as Complaint,
dgfDocument as Document,
dgfItem as Item,
get_auction,
validate_features_uniq,
validate_lots_uniq,
validate_items_uniq,
calc_auction_end_time,
validate_lots_uniq,
validate_not_available,
FinancialOrganization
)
from openprocurement.auctions.core.models.roles import (
dgf_auction_roles,
)
from openprocurement.auctions.core.plugins.awarding.v3.models import (
Award
Expand All @@ -54,16 +54,19 @@
Contract,
)
from openprocurement.auctions.core.utils import (
rounding_shouldStartAfter_after_midnigth,
AUCTIONS_COMPLAINT_STAND_STILL_TIME,
TZ,
calculate_business_date,
get_request_from_root,
get_now,
TZ
get_request_from_root,
rounding_shouldStartAfter_after_midnigth,
)
from openprocurement.auctions.core.validation import (
validate_disallow_dgfPlatformLegalDetails
)
from openprocurement.auctions.dgf.constants import (
RECTIFICATION_PERIOD_DURATION,
)


class DGFOtherBid(BaseBid):
Expand Down Expand Up @@ -111,29 +114,52 @@ class IDgfFinancialAssetsAuction(IAuction):

@implementer(IDgfOtherAssetsAuction)
class DGFOtherAssets(BaseAuction):
"""Data regarding auction process - publicly inviting prospective contractors to submit bids for evaluation and selecting a winner or winners."""
"""Data regarding auction process

publicly inviting prospective contractors to submit bids
for evaluation and selecting a winner or winners.
"""
class Options:
roles = dgf_auction_roles
_procedure_type = "dgfOtherAssets"
awards = ListType(ModelType(Award), default=list())
bids = ListType(ModelType(DGFOtherBid), default=list()) # A list of all the companies who entered submissions for the auction.
# A list of all the companies who entered submissions for the auction.
bids = ListType(ModelType(DGFOtherBid), default=list())
cancellations = ListType(ModelType(Cancellation), default=list())
complaints = ListType(ComplaintModelType(Complaint), default=list())
contracts = ListType(ModelType(Contract), default=list())
dgfID = StringType()
merchandisingObject = MD5Type()
dgfDecisionID = StringType()
dgfDecisionDate = DateType()
documents = ListType(ModelType(Document), default=list()) # All documents and attachments related to the auction.
enquiryPeriod = ModelType(Period) # The period during which enquiries may be made and will be answered.
tenderPeriod = ModelType(Period) # The period when the auction is open for submissions. The end date is the closing date for auction submissions.
# All documents and attachments related to the auction.
documents = ListType(ModelType(Document), default=list())
# The period during which enquiries may be made and will be answered.
enquiryPeriod = ModelType(Period)
# The period when the auction is open for submissions. The end date is the closing date for auction submissions.
tenderPeriod = ModelType(Period)
tenderAttempts = IntType(choices=[1, 2, 3, 4, 5, 6, 7, 8])
auctionPeriod = ModelType(AuctionAuctionPeriod, required=True, default={})
status = StringType(choices=['draft', 'pending.verification', 'invalid', 'active.tendering', 'active.auction', 'active.qualification', 'active.awarded', 'complete', 'cancelled', 'unsuccessful'], default='active.tendering')
status = StringType(
choices=[
'draft',
'pending.verification',
'invalid',
'active.tendering',
'active.auction',
'active.qualification',
'active.awarded',
'complete',
'cancelled',
'unsuccessful'
],
default='active.tendering'
)
features = ListType(ModelType(Feature), validators=[validate_features_uniq, validate_not_available])
lots = ListType(ModelType(Lot), default=list(), validators=[validate_lots_uniq, validate_not_available])
items = ListType(ModelType(Item), default=list(), validators=[validate_items_uniq])
suspended = BooleanType()
rectificationPeriod = ModelType(RectificationPeriod)

def __acl__(self):
return [
Expand All @@ -153,10 +179,41 @@ def get_role(self):
role = 'auction_{}'.format(request.method.lower())
elif request.authenticated_role == 'convoy':
role = 'convoy'
else:
role = 'edit_{}'.format(request.context.status)
else: # on PATCH of the owner
now = get_now()
if self.status == 'active.tendering':
if now in self.rectificationPeriod:
role = 'edit_active.tendering_during_rectificationPeriod'
else:
role = 'edit_active.tendering_after_rectificationPeriod'
else:
role = 'edit_{0}'.format(self.status)
return role

@serializable(serialized_name='rectificationPeriod', serialize_when_none=False)
def generate_rectificationPeriod(self):
"""Generate rectificationPeriod only when it not defined"""
# avoid period generation if
if (
# it's already generated
(
getattr(self, 'rectificationPeriod', False)
# and not just present, but actually holds some real value
and self.rectificationPeriod.startDate is not None
)
# or trere's no period on that our code is dependant
or getattr(self, 'tenderPeriod') is None
):
return
start = self.tenderPeriod.startDate
end = calculate_business_date(start, RECTIFICATION_PERIOD_DURATION, self, working_days=True)

period = RectificationPeriod()
period.startDate = start
period.endDate = end

return period.serialize()

def initialize(self):
if not self.enquiryPeriod:
self.enquiryPeriod = type(self).enquiryPeriod.model_class()
Expand Down Expand Up @@ -212,7 +269,6 @@ def validate_items(self, data, items):
elif len(items) < 1:
raise ValidationError(u'Please provide at least 1 item.')


@serializable(serialize_when_none=False)
def next_check(self):
if self.suspended:
Expand Down Expand Up @@ -255,6 +311,7 @@ def next_check(self):
checks.append(calculate_business_date(complaint.dateAnswered, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self))
return min(checks).isoformat() if checks else None


class DGFFinancialBid(DGFOtherBid):
class Options:
roles = {
Expand All @@ -273,4 +330,3 @@ class DGFFinancialAssets(DGFOtherAssets):
eligibilityCriteria = StringType(default=DGF_ELIGIBILITY_CRITERIA['ua'])
eligibilityCriteria_en = StringType(default=DGF_ELIGIBILITY_CRITERIA['en'])
eligibilityCriteria_ru = StringType(default=DGF_ELIGIBILITY_CRITERIA['ru'])

8 changes: 7 additions & 1 deletion openprocurement/auctions/dgf/tests/auction.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
from openprocurement.auctions.core.tests.auctions import (
AuctionAuctionResourceTestMixin,
AuctionLotAuctionResourceTestMixin,
AuctionMultipleLotAuctionResourceTestMixin
AuctionMultipleLotAuctionResourceTestMixin,
AuctionRectificationPeriodTestMixin,
)
from openprocurement.auctions.core.tests.blanks.auction_blanks import (
submission_method_details_no_auction,
Expand Down Expand Up @@ -276,6 +277,11 @@ class FinancialAuctionSubmissionMethodDetailsTestWithRegistry(FinancialAuctionSu
registry = True


class OtherAssetsAuctionRectificationPeriodTest(BaseAuctionWebTest, AuctionRectificationPeriodTestMixin):
initial_status = 'active.tendering'
initial_bids = test_bids


def suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(AuctionAuctionResourceTest))
Expand Down
Loading