Skip to content

Commit

Permalink
Merge branch 'a200954328936723_blocking_questions'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmaksymiv committed Oct 29, 2016
2 parents 80e0395 + 8c2231a commit e54dab6
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 8 deletions.
5 changes: 2 additions & 3 deletions openprocurement/tender/openua/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
)
from openprocurement.api.models import ITender
from openprocurement.tender.openua.utils import (
calculate_business_date,
calculate_business_date, has_unanswered_questions, has_unanswered_complaints
)

edit_role_ua = edit_role + blacklist('enquiryPeriod', 'status')
Expand Down Expand Up @@ -524,8 +524,7 @@ def next_check(self):
now = get_now()
checks = []
if self.status == 'active.tendering' and self.tenderPeriod.endDate and \
not any([i.status in self.block_tender_complaint_status for i in self.complaints]) and \
not any([i.id for i in self.questions if not i.answer]):
not has_unanswered_complaints(self) and not has_unanswered_questions(self):
checks.append(self.tenderPeriod.endDate.astimezone(TZ))
elif not self.lots and self.status == 'active.auction' and self.auctionPeriod and self.auctionPeriod.startDate and not self.auctionPeriod.endDate:
if now < self.auctionPeriod.startDate:
Expand Down
155 changes: 154 additions & 1 deletion openprocurement/tender/openua/tests/lot.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from datetime import timedelta

from openprocurement.api.models import get_now
from openprocurement.api.tests.base import test_lots, test_organization
from openprocurement.api.tests.base import test_lots, test_bids, test_organization
from openprocurement.tender.openua.tests.base import BaseTenderUAContentWebTest, test_tender_data


Expand Down Expand Up @@ -633,6 +633,159 @@ def test_tender_lot_guarantee(self):
self.assertEqual(response.json['data']['guarantee']['currency'], "GBP")


class TenderLotEdgeCasesTest(BaseTenderUAContentWebTest):
initial_lots = test_lots * 2
initial_bids = test_bids

def test_question_blocking(self):
self.app.authorization = ('Basic', ('broker', ''))
response = self.app.post_json('/tenders/{}/questions'.format(self.tender_id),
{'data': {'title': 'question title',
'description': 'question description',
'questionOf': 'lot',
'relatedItem': self.initial_lots[0]['id'],
'author': test_organization}})
question = response.json['data']
self.assertEqual(question['questionOf'], 'lot')
self.assertEqual(question['relatedItem'], self.initial_lots[0]['id'])

self.set_status('active.auction', extra={"status": "active.tendering"})
self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})

self.app.authorization = ('Basic', ('broker', ''))
response = self.app.get('/tenders/{}'.format(self.tender_id))
self.assertEqual(response.json['data']['status'], 'active.tendering')

# cancel lot
response = self.app.post_json('/tenders/{}/cancellations?acc_token={}'.format(self.tender_id, self.tender_token),
{'data': {'reason': 'cancellation reason',
'status': 'active',
"cancellationOf": "lot",
"relatedLot": self.initial_lots[0]['id']}})

self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {"data": {"id": self.tender_id}})

self.app.authorization = ('Basic', ('broker', ''))
response = self.app.get('/tenders/{}'.format(self.tender_id))
self.assertEqual(response.json['data']['status'], 'active.auction')

def test_claim_blocking(self):
self.app.authorization = ('Basic', ('broker', ''))
response = self.app.post_json('/tenders/{}/complaints'.format(self.tender_id),
{'data': {'title': 'complaint title',
'description': 'complaint description',
'author': test_organization,
'relatedLot': self.initial_lots[0]['id'],
'status': 'claim'}})
self.assertEqual(response.status, '201 Created')
complaint = response.json['data']
owner_token = response.json['access']['token']
self.assertEqual(complaint['relatedLot'], self.initial_lots[0]['id'])

self.set_status('active.auction', extra={"status": "active.tendering"})
self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})

self.app.authorization = ('Basic', ('broker', ''))
response = self.app.get('/tenders/{}'.format(self.tender_id))
self.assertEqual(response.json['data']['status'], 'active.tendering')

# cancel lot
response = self.app.post_json('/tenders/{}/cancellations?acc_token={}'.format(self.tender_id, self.tender_token),
{'data': {'reason': 'cancellation reason',
'status': 'active',
"cancellationOf": "lot",
"relatedLot": self.initial_lots[0]['id']}})

self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {"data": {"id": self.tender_id}})

self.app.authorization = ('Basic', ('broker', ''))
response = self.app.get('/tenders/{}'.format(self.tender_id))
self.assertEqual(response.json['data']['status'], 'active.auction')

def test_next_check_value_with_unanswered_question(self):
self.app.authorization = ('Basic', ('broker', ''))
response = self.app.post_json('/tenders/{}/questions'.format(self.tender_id),
{'data': {'title': 'question title',
'description': 'question description',
'questionOf': 'lot',
'relatedItem': self.initial_lots[0]['id'],
'author': test_organization}})
question = response.json['data']
self.assertEqual(question['questionOf'], 'lot')
self.assertEqual(question['relatedItem'], self.initial_lots[0]['id'])

self.set_status('active.auction', extra={"status": "active.tendering"})
self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.json['data']["status"], 'active.tendering')
self.assertNotIn('next_check', response.json['data'])

self.app.authorization = ('Basic', ('broker', ''))
response = self.app.post_json('/tenders/{}/cancellations?acc_token={}'.format(self.tender_id, self.tender_token),
{'data': {'reason': 'cancellation reason',
'status': 'active',
"cancellationOf": "lot",
"relatedLot": self.initial_lots[0]['id']}})

response = self.app.get('/tenders/{}'.format(self.tender_id, ))
self.assertIn('next_check', response.json['data'])
self.assertEqual(response.json['data']['next_check'], response.json['data']['tenderPeriod']['endDate'])

self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.json['data']["status"], 'active.auction')
self.assertIn('next_check', response.json['data'])
self.assertGreater(response.json['data']['next_check'], response.json['data']['tenderPeriod']['endDate'])

def test_next_check_value_with_unanswered_claim(self):
self.app.authorization = ('Basic', ('broker', ''))
response = self.app.post_json('/tenders/{}/complaints'.format(self.tender_id),
{'data': {'title': 'complaint title',
'description': 'complaint description',
'author': test_organization,
'relatedLot': self.initial_lots[0]['id'],
'status': 'claim'}})
self.assertEqual(response.status, '201 Created')
complaint = response.json['data']
owner_token = response.json['access']['token']
self.assertEqual(complaint['relatedLot'], self.initial_lots[0]['id'])

self.set_status('active.auction', extra={"status": "active.tendering"})
self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.json['data']["status"], 'active.tendering')
self.assertNotIn('next_check', response.json['data'])

self.app.authorization = ('Basic', ('broker', ''))
response = self.app.post_json('/tenders/{}/cancellations?acc_token={}'.format(self.tender_id, self.tender_token),
{'data': {'reason': 'cancellation reason',
'status': 'active',
"cancellationOf": "lot",
"relatedLot": self.initial_lots[0]['id']}})

response = self.app.get('/tenders/{}'.format(self.tender_id, ))
self.assertIn('next_check', response.json['data'])
self.assertEqual(response.json['data']['next_check'], response.json['data']['tenderPeriod']['endDate'])

self.app.authorization = ('Basic', ('chronograph', ''))
response = self.app.patch_json('/tenders/{}'.format(self.tender_id), {'data': {'id': self.tender_id}})
self.assertEqual(response.status, '200 OK')
self.assertEqual(response.content_type, 'application/json')
self.assertEqual(response.json['data']["status"], 'active.auction')
self.assertIn('next_check', response.json['data'])
self.assertGreater(response.json['data']['next_check'], response.json['data']['tenderPeriod']['endDate'])


class TenderLotFeatureResourceTest(BaseTenderUAContentWebTest):
initial_lots = 2 * test_lots

Expand Down
21 changes: 17 additions & 4 deletions openprocurement/tender/openua/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,26 @@ def check_complaint_status(request, complaint):
complaint.status = complaint.resolutionType


def has_unanswered_questions(tender, filter_cancelled_lots=True):
if filter_cancelled_lots and tender.lots:
active_lots = [l.id for l in tender.lots if l.status == 'active']
return any([i.id for i in tender.questions if i.relatedItem in active_lots and not i.answer])
return any([i.id for i in tender.questions if not i.answer])


def has_unanswered_complaints(tender, filter_cancelled_lots=True):
if filter_cancelled_lots and tender.lots:
active_lots = [l.id for l in tender.lots if l.status == 'active']
return any([i.status in tender.block_tender_complaint_status for i in tender.complaints if not i.relatedLot \
or (i.relatedLot and i.relatedLot in active_lots)])
return any([i.status in tender.block_tender_complaint_status for i in tender.complaints])


def check_status(request):
tender = request.validated['tender']
now = get_now()
if not tender.lots and tender.status == 'active.tendering' and tender.tenderPeriod.endDate <= now and \
not any([i.status in tender.block_tender_complaint_status for i in tender.complaints]) and \
not any([i.id for i in tender.questions if not i.answer]):
not has_unanswered_complaints(tender) and not has_unanswered_questions(tender):
for complaint in tender.complaints:
check_complaint_status(request, complaint)
LOGGER.info('Switched tender {} to {}'.format(tender['id'], 'active.auction'),
Expand All @@ -51,8 +65,7 @@ def check_status(request):
tender.auctionPeriod.startDate = None
return
elif tender.lots and tender.status == 'active.tendering' and tender.tenderPeriod.endDate <= now and \
not any([i.status in tender.block_tender_complaint_status for i in tender.complaints]) and \
not any([i.id for i in tender.questions if not i.answer]):
not has_unanswered_complaints(tender) and not has_unanswered_questions(tender):
for complaint in tender.complaints:
check_complaint_status(request, complaint)
LOGGER.info('Switched tender {} to {}'.format(tender['id'], 'active.auction'),
Expand Down

0 comments on commit e54dab6

Please sign in to comment.