def suspended_auction(self): self.app.authorization = ('Basic', ('broker', '')) # empty auctions listing response = self.app.get('/auctions') self.assertEqual(response.json['data'], []) # create auction auction_data = deepcopy(self.initial_data) auction_data['suspended'] = True response = self.app.post_json('/auctions', {"data": auction_data}) auction_id = self.auction_id = response.json['data']['id'] owner_token = response.json['access']['token'] self.assertNotIn('suspended', response.json['data']) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": True}}, status=403) self.assertEqual(response.status, '403 Forbidden') authorization = self.app.authorization self.app.authorization = ('Basic', ('administrator', '')) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": True}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], True) self.assertNotIn('next_check', response.json['data']) self.app.authorization = authorization response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": False}}, status=403) self.assertEqual(response.status, '403 Forbidden') self.app.authorization = ('Basic', ('administrator', '')) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": False}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], False) self.assertIn('next_check', response.json['data']) self.app.authorization = authorization # switch to active.tendering self.set_status('active.tendering') # create bid self.app.authorization = ('Basic', ('broker', '')) if self.initial_organization == self.test_financial_organization: response = self.app.post_json('/auctions/{}/bids'.format(auction_id), {'data': {'tenderers': [self.initial_organization], "value": {"amount": 450}, 'qualified': True, 'eligible': True}}) else: response = self.app.post_json('/auctions/{}/bids'.format(auction_id), {'data': {'tenderers': [self.initial_organization], "value": {"amount": 450}, 'qualified': True}}) bid_id = response.json['data']['id'] bid_token = response.json['access']['token'] # create second bid self.app.authorization = ('Basic', ('broker', '')) if self.initial_organization == self.test_financial_organization: response = self.app.post_json('/auctions/{}/bids'.format(auction_id), {'data': {'tenderers': [self.initial_organization], "value": {"amount": 450}, 'qualified': True, 'eligible': True}}) else: response = self.app.post_json('/auctions/{}/bids'.format(auction_id), {'data': {'tenderers': [self.initial_organization], "value": {"amount": 450}, 'qualified': True}}) authorization = self.app.authorization self.app.authorization = ('Basic', ('administrator', '')) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": True}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], True) self.assertNotIn('next_check', response.json['data']) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": False}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], False) self.assertIn('next_check', response.json['data']) self.app.authorization = authorization # switch to active.auction self.set_status('active.auction') # get auction info self.app.authorization = ('Basic', ('auction', '')) response = self.app.get('/auctions/{}/auction'.format(auction_id)) auction_bids_data = response.json['data']['bids'] # check bid participationUrl self.app.authorization = ('Basic', ('broker', '')) response = self.app.get('/auctions/{}/bids/{}?acc_token={}'.format(auction_id, bid_id, bid_token)) self.assertIn('participationUrl', response.json['data']) # posting auction results self.app.authorization = ('Basic', ('auction', '')) response = self.app.get('/auctions/{}'.format(self.auction_id)) self.assertEqual(response.status, '200 OK') auction = response.json['data'] value_threshold = auction['value']['amount'] + auction['minimalStep']['amount'] now = get_now() auction_result = { 'bids': [ { "id": b['id'], "date": (now - timedelta(seconds=i)).isoformat(), "value": {"amount": value_threshold * 2}, } for i, b in enumerate(auction_bids_data) ] } response = self.app.post_json('/auctions/{}/auction'.format(self.auction_id), {'data': auction_result}) # get awards self.app.authorization = ('Basic', ('broker', '')) response = self.app.get('/auctions/{}/awards?acc_token={}'.format(auction_id, owner_token)) # get pending award award_id = [i['id'] for i in response.json['data'] if i['status'] == 'pending'][0] authorization = self.app.authorization self.app.authorization = ('Basic', ('administrator', '')) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": True}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], True) self.assertNotIn('next_check', response.json['data']) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": False}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], False) self.app.authorization = authorization # set award as unsuccessful self.app.authorization = ('Basic', ('broker', '')) response = self.app.post_json( '/auctions/{}/awards/{}/documents?acc_token={}'.format(self.auction_id, award_id, owner_token), params={ 'data': { 'documentType': 'rejectionProtocol', 'title': 'rejection protocol', 'format': 'application/msword', 'url': self.generate_docservice_url(), 'hash': 'md5:' + '0' * 32 } }) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']['title'], 'rejection protocol') self.assertEqual(response.json['data']['documentType'], 'rejectionProtocol') response = self.app.patch_json('/auctions/{}/awards/{}?acc_token={}'.format(auction_id, award_id, owner_token), {"data": {"status": "unsuccessful"}}) self.assertEqual(response.json['data']['status'], 'unsuccessful') # get awards self.app.authorization = ('Basic', ('broker', '')) response = self.app.get('/auctions/{}/awards?acc_token={}'.format(auction_id, owner_token)) self.assertEqual(len(response.json['data']), 2) self.assertEqual(response.json['data'][0]['status'], 'unsuccessful') # get pending award award2_id = [i['id'] for i in response.json['data'] if i['status'] == 'pending'][0] self.assertNotEqual(award_id, award2_id) self.app.authorization = ('Basic', ('broker', '')) response = self.app.get('/auctions/{}/awards?acc_token={}'.format(auction_id, owner_token)) # get pending award award_id = [i['id'] for i in response.json['data'] if i['status'] == 'pending'][0] response = self.app.post('/auctions/{}/awards/{}/documents?acc_token={}'.format( self.auction_id, award_id, owner_token), upload_files=[('file', 'auction_protocol.pdf', 'content')]) doc_id = response.json["data"]['id'] response = self.app.patch_json('/auctions/{}/awards/{}/documents/{}?acc_token={}'.format(auction_id, award_id, doc_id, owner_token), {"data": {"documentType": 'auctionProtocol'}}) # set award as active self.app.patch_json('/auctions/{}/awards/{}?acc_token={}'.format(auction_id, award_id, owner_token), {"data": {"status": "active"}}) authorization = self.app.authorization self.app.authorization = ('Basic', ('administrator', '')) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": True}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], True) self.assertNotIn('next_check', response.json['data']) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": False}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], False) self.app.authorization = authorization response = self.app.patch_json( '/auctions/{}/awards/{}?acc_token={}'.format(auction_id, award_id, owner_token), {"data": {"status": "active"}}, status=403 ) self.assertEqual(response.json['errors'][0]['description'], "Can\'t update award in current (active) status") # get contract id response = self.app.get('/auctions/{}'.format(auction_id)) contract_id = response.json['data']['contracts'][-1]['id'] authorization = self.app.authorization self.app.authorization = ('Basic', ('administrator', '')) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": True}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], True) self.assertNotIn('next_check', response.json['data']) response = self.app.patch_json('/auctions/{}'.format(auction_id), {"data": {"suspended": False}}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['suspended'], False) self.app.authorization = authorization # create auction contract document for test response = self.app.post('/auctions/{}/contracts/{}/documents?acc_token={}'.format(auction_id, contract_id, owner_token), upload_files=[('file', 'name.doc', 'content')], status=201) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] self.assertIn(doc_id, response.headers['Location']) # after stand slill period self.app.authorization = ('Basic', ('chronograph', '')) self.set_status('complete', {'status': 'active.awarded'}) # time travel auction = self.db.get(auction_id) for i in auction.get('awards', []): i['complaintPeriod']['endDate'] = i['complaintPeriod']['startDate'] self.db.save(auction) # sign contract self.app.authorization = ('Basic', ('broker', '')) # Upload document response = self.app.post_json( '/auctions/{}/contracts/{}/documents?acc_token={}'.format(self.auction_id, contract_id, owner_token), params={ 'data': { 'documentType': 'contractSigned', 'title': 'Signed contract', 'format': 'application/msword', 'url': self.generate_docservice_url(), 'hash': 'md5:' + '0' * 32 } }) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']['title'], 'Signed contract') self.assertEqual(response.json['data']['documentType'], 'contractSigned') # Patch dateSigned field signature_date = get_now().isoformat() response = self.app.patch_json('/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract_id, owner_token ), {"data": {"dateSigned": signature_date}}) self.assertEqual(response.status, '200 OK') response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format(auction_id, contract_id, owner_token), {"data": {"status": "active"}} ) self.assertEqual(response.json['data']['status'], 'active') # check status self.app.authorization = ('Basic', ('broker', '')) response = self.app.get('/auctions/{}'.format(auction_id)) self.assertEqual(response.json['data']['status'], 'complete')
def next_check(self): if self.suspended: return None now = get_now() checks = [] if self.status == 'active.tendering' and self.tenderPeriod and self.tenderPeriod.endDate: 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: checks.append(self.auctionPeriod.startDate.astimezone(TZ)) elif now < calc_auction_end_time( self.numberOfBids, self.auctionPeriod.startDate).astimezone(TZ): checks.append( calc_auction_end_time( self.numberOfBids, self.auctionPeriod.startDate).astimezone(TZ)) elif self.lots and self.status == 'active.auction': for lot in self.lots: if lot.status != 'active' or not lot.auctionPeriod or not lot.auctionPeriod.startDate or lot.auctionPeriod.endDate: continue if now < lot.auctionPeriod.startDate: checks.append(lot.auctionPeriod.startDate.astimezone(TZ)) elif now < calc_auction_end_time( lot.numberOfBids, lot.auctionPeriod.startDate).astimezone(TZ): checks.append( calc_auction_end_time( lot.numberOfBids, lot.auctionPeriod.startDate).astimezone(TZ)) # Use next_check part from awarding 2.0 request = get_request_from_root(self) if request is not None: awarding_check = request.registry.getAdapter( self, IAwardingNextCheck).add_awarding_checks(self) if awarding_check is not None: checks.append(awarding_check) if self.status.startswith('active'): from openprocurement.auctions.core.utils import calculate_business_date for complaint in self.complaints: if complaint.status == 'claim' and complaint.dateSubmitted: checks.append( calculate_business_date( complaint.dateSubmitted, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) elif complaint.status == 'answered' and complaint.dateAnswered: checks.append( calculate_business_date( complaint.dateAnswered, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) for award in self.awards: for complaint in award.complaints: if complaint.status == 'claim' and complaint.dateSubmitted: checks.append( calculate_business_date( complaint.dateSubmitted, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) elif complaint.status == 'answered' and complaint.dateAnswered: checks.append( calculate_business_date( complaint.dateAnswered, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) return min(checks).isoformat() if checks else None
from openprocurement.auctions.geb.tests.fixtures.cancellations import ( CANCELLATION, CANCELLATION_WITH_DOCUMENTS) from openprocurement.auctions.geb.tests.fixtures.documents import ( DOCUMENT, OFFLINE_DOCUMENT) from openprocurement.auctions.geb.tests.fixtures.bids import ( BID_ACTIVE_FIRST, BID_ACTIVE_SECOND, BID_ACTIVE_FIRST_WITH_DOCUMENT, BID_DRAFT_WITH_DOCUMENT, BID_PENDING_FIRST, BID_PENDING_FIRST_WITH_DOCUMENT, BID_PENDING_SECOND, ) from openprocurement.auctions.geb.tests.fixtures.calculator import (Calculator) now = get_now() calculator = Calculator(now, 'enquiryPeriod', 'start') auction = deepcopy(END_ACTIVE_TENDERING_AUCTION_WITH_TWO_BIDS) auction['status'] = 'active.enquiry' auction["rectificationPeriod"] = { "startDate": calculator.rectificationPeriod.startDate.isoformat(), "endDate": calculator.rectificationPeriod.endDate.isoformat() } auction["tenderPeriod"] = { "startDate": calculator.tenderPeriod.startDate.isoformat(), "endDate": calculator.tenderPeriod.endDate.isoformat() } auction["enquiryPeriod"] = { "startDate": calculator.enquiryPeriod.startDate.isoformat(), "endDate": calculator.enquiryPeriod.endDate.isoformat() }
# -*- coding: utf-8 -*- from datetime import timedelta from openprocurement.auctions.core.plugins.contracting.v3.models import ( Prolongation, ) from openprocurement.auctions.core.utils import get_now PROLONGATION = { 'decisionID': 'very_importante_documente', 'description': 'Prolongate your contract for free!', 'reason': 'other', 'documents': [], 'datePublished': get_now().isoformat(), } def create_award(test_case): # Create award authorization = test_case.app.authorization test_case.app.authorization = ('Basic', ('auction', '')) now = get_now() auction_result = { 'bids': [{ "id": b['id'], "date": (now - timedelta(seconds=i)).isoformat(), "value": b['value'] } for i, b in enumerate(test_case.initial_bids)] } response = test_case.app.post_json( '/auctions/{}/auction'.format(test_case.auction_id), {'data': auction_result})
def validate_dgfDecisionDate(self, data, dgfID): if not dgfID: if (data.get('revisions')[0].date if data.get('revisions') else get_now()) > DGF_DECISION_REQUIRED_FROM: raise ValidationError(u'This field is required.')
# -*- coding: utf-8 -*- from uuid import uuid4 from copy import deepcopy from datetime import timedelta from openprocurement.auctions.core.utils import get_now from openprocurement.auctions.geb.tests.fixtures.common import ( test_auctionParameters, test_auction_budgetSpent_created, test_auction_minimalStep_created, test_auction_value_created, test_contractTerms, test_lotHolder, test_bankAccount, test_procuringEntity, test_registrationFee_created, test_transfer_token, test_auction_guarantee) from openprocurement.auctions.geb.tests.fixtures.items import (TEST_ITEM) now = get_now() AUCTION = { "_id": uuid4().hex, "procurementMethod": "open", "auctionID": "UA-EA-2018-09-20-000001", "minNumberOfQualifiedBids": 2, "submissionMethod": "electronicAuction", "awardCriteria": "highestCost", "owner": "broker", "transfer_token": test_transfer_token, "title": "футляри до державних нагород", "tenderAttempts": 1, 'bankAccount': test_bankAccount, "registrationFee": test_registrationFee_created, "owner_token": uuid4().hex, "auctionParameters": test_auctionParameters, "guarantee": test_auction_guarantee, "dateModified": now.isoformat(),
def get_auction_creation_date(data): auction_creation_date = (data.get('revisions')[0].date if data.get('revisions') else get_now()) return auction_creation_date
from datetime import timedelta from copy import deepcopy from openprocurement.auctions.geb.tests.fixtures.active_auction import ( AUCTION as ACTIVE_AUCTION_AUCTION) from openprocurement.auctions.core.utils import get_now from openprocurement.auctions.geb.tests.fixtures.calculator import (Calculator) from openprocurement.auctions.geb.tests.fixtures.awards import ( AWARD_PENDING, AWARD_PENDING_WITH_PROTOCOL) from openprocurement.auctions.geb.tests.fixtures.documents import ( AUCTION_DOCUMENT_AUDIT) from openprocurement.auctions.geb.utils import ( calculate_certainly_business_date as ccbd) qualification_period_start = ccbd(get_now(), -timedelta(days=1), specific_hour=16) calculator = Calculator(qualification_period_start, 'qualificationPeriod', 'start') auction = deepcopy(ACTIVE_AUCTION_AUCTION) auction['status'] = 'active.qualification' auction['documents'] = [AUCTION_DOCUMENT_AUDIT] auction["rectificationPeriod"] = { "startDate": calculator.rectificationPeriod.startDate.isoformat(), "endDate": calculator.rectificationPeriod.endDate.isoformat() } auction["tenderPeriod"] = { "startDate": calculator.tenderPeriod.startDate.isoformat(), "endDate": calculator.tenderPeriod.endDate.isoformat() }
def patch_auction_contract(self): response = self.app.get('/auctions/{}/contracts'.format(self.auction_id)) contract = response.json['data'][0] response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "status": "active" }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.content_type, 'application/json') self.assertIn("Can't sign contract before stand-still period end (", response.json['errors'][0]["description"]) self.set_status('complete', {'status': 'active.awarded'}) response = self.app.post_json( '/auctions/{}/awards/{}/complaints?acc_token={}'.format( self.auction_id, self.award_id, self.first_bid_token), { 'data': { 'title': 'complaint title', 'description': 'complaint description', 'author': self.initial_organization, 'status': 'claim' } }) self.assertEqual(response.status, '201 Created') complaint = response.json['data'] owner_token = response.json['access']['token'] auction = self.db.get(self.auction_id) for i in auction.get('awards', []): i['complaintPeriod']['endDate'] = i['complaintPeriod']['startDate'] self.db.save(auction) response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), { "data": { "contractID": "myselfID", "items": [{ "description": "New Description" }], "suppliers": [{ "name": "New Name" }] } }) self.assertEqual(response.status, '200 OK') response = self.app.get('/auctions/{}/contracts/{}'.format( self.auction_id, contract['id'])) self.assertEqual(response.json['data']['contractID'], contract['contractID']) self.assertEqual(response.json['data']['items'], contract['items']) self.assertEqual(response.json['data']['suppliers'], contract['suppliers']) response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "value": { "currency": "USD" } }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]["description"], "Can\'t update currency for contract value") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "value": { "valueAddedTaxIncluded": False } }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.json['errors'][0]["description"], "Can\'t update valueAddedTaxIncluded for contract value") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "value": { "amount": 99 } }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]["description"], "Value amount should be greater or equal to awarded amount (479)") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "value": { "amount": 500 } }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']['value']['amount'], 500) response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "dateSigned": i['complaintPeriod']['endDate'] }}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.json['errors'], [{ u'description': [ u'Contract signature date should be after award complaint period end date ({})' .format(i['complaintPeriod']['endDate']) ], u'location': u'body', u'name': u'dateSigned' }]) one_hour_in_future = (get_now() + timedelta(hours=1)).isoformat() response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "dateSigned": one_hour_in_future }}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual( response.json['errors'], [{ u'description': [u"Contract signature date can't be in the future"], u'location': u'body', u'name': u'dateSigned' }]) custom_signature_date = get_now().isoformat() response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "dateSigned": custom_signature_date }}) self.assertEqual(response.status, '200 OK') response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "status": "active" }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['errors'][0]["description"], "Can't sign contract before reviewing all complaints") response = self.app.patch_json( '/auctions/{}/awards/{}/complaints/{}?acc_token={}'.format( self.auction_id, self.award_id, complaint['id'], self.auction_token), { "data": { "status": "answered", "resolutionType": "resolved", "resolution": "resolution text " * 2 } }) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']["status"], "answered") self.assertEqual(response.json['data']["resolutionType"], "resolved") self.assertEqual(response.json['data']["resolution"], "resolution text " * 2) response = self.app.patch_json( '/auctions/{}/awards/{}/complaints/{}?acc_token={}'.format( self.auction_id, self.award_id, complaint['id'], owner_token), {"data": { "satisfied": True, "status": "resolved" }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']["status"], "resolved") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "status": "active" }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']["status"], "active") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "value": { "amount": 232 } }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]["description"], "Can't update contract in current (complete) auction status") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "contractID": "myselfID" }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]["description"], "Can't update contract in current (complete) auction status") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "items": [{ "description": "New Description" }] }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]["description"], "Can't update contract in current (complete) auction status") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "suppliers": [{ "name": "New Name" }] }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual( response.json['errors'][0]["description"], "Can't update contract in current (complete) auction status") response = self.app.patch_json( '/auctions/{}/contracts/{}?acc_token={}'.format( self.auction_id, contract['id'], self.auction_token), {"data": { "status": "active" }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.content_type, 'application/json') self.assertEqual( response.json['errors'][0]["description"], "Can't update contract in current (complete) auction status") response = self.app.patch_json('/auctions/{}/contracts/some_id'.format( self.auction_id), {"data": { "status": "active" }}, status=404) self.assertEqual(response.status, '404 Not Found') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [{ u'description': u'Not Found', u'location': u'url', u'name': u'contract_id' }]) response = self.app.patch_json('/auctions/some_id/contracts/some_id', {"data": { "status": "active" }}, status=404) self.assertEqual(response.status, '404 Not Found') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [{ u'description': u'Not Found', u'location': u'url', u'name': u'auction_id' }]) response = self.app.get('/auctions/{}/contracts/{}'.format( self.auction_id, contract['id'])) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']["status"], "active") self.assertEqual(response.json['data']["value"]['amount'], 500) self.assertEqual(response.json['data']['contractID'], contract['contractID']) self.assertEqual(response.json['data']['items'], contract['items']) self.assertEqual(response.json['data']['suppliers'], contract['suppliers']) self.assertEqual(response.json['data']['dateSigned'], custom_signature_date)
def patch(self): """Post a complaint resolution """ auction = self.request.validated['auction'] if auction.status not in [ 'active.tendering', 'active.auction', 'active.qualification', 'active.awarded' ]: self.request.errors.add( 'body', 'data', 'Can\'t update complaint in current ({}) auction status'. format(auction.status)) self.request.errors.status = 403 return if self.context.status not in [ 'draft', 'claim', 'answered', 'pending' ]: self.request.errors.add( 'body', 'data', 'Can\'t update complaint in current ({}) status'.format( self.context.status)) self.request.errors.status = 403 return data = self.request.validated['data'] # complaint_owner if self.request.authenticated_role == 'complaint_owner' and self.context.status in [ 'draft', 'claim', 'answered', 'pending' ] and data.get('status', self.context.status) == 'cancelled': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateCanceled = get_now() elif self.request.authenticated_role == 'complaint_owner' and auction.status in [ 'active.tendering' ] and self.context.status == 'draft' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and auction.status in [ 'active.tendering' ] and self.context.status == 'draft' and data.get( 'status', self.context.status) == 'claim': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateSubmitted = get_now() elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'satisfied', self.context.satisfied) is True and data.get( 'status', self.context.status) == 'resolved': apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'complaint_owner' and self.context.status == 'answered' and data.get( 'satisfied', self.context.satisfied) is False and data.get( 'status', self.context.status) == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) self.context.type = 'complaint' self.context.dateEscalated = get_now() elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'claim' and data.get( 'resolution', self.context.resolution) and data.get( 'resolutionType', self.context.resolutionType) and data.get( 'status', self.context.status) == 'answered': if len(data.get('resolution', self.context.resolution)) < 20: self.request.errors.add( 'body', 'data', 'Can\'t update complaint: resolution too short') self.request.errors.status = 403 return apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateAnswered = get_now() elif self.request.authenticated_role == 'auction_owner' and self.context.status == 'pending': apply_patch(self.request, save=False, src=self.context.serialize()) # reviewers elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get( 'status', self.context.status) == self.context.status: apply_patch(self.request, save=False, src=self.context.serialize()) elif self.request.authenticated_role == 'reviewers' and self.context.status == 'pending' and data.get( 'status', self.context.status) in ['resolved', 'invalid', 'declined']: apply_patch(self.request, save=False, src=self.context.serialize()) self.context.dateDecision = get_now() else: self.request.errors.add('body', 'data', 'Can\'t update complaint') self.request.errors.status = 403 return if self.context.tendererAction and not self.context.tendererActionDate: self.context.tendererActionDate = get_now() if self.context.status not in [ 'draft', 'claim', 'answered', 'pending' ] and auction.status in ['active.qualification', 'active.awarded']: check_auction_status(self.request) if save_auction(self.request): self.LOGGER.info( 'Updated auction complaint {}'.format(self.context.id), extra=context_unpack( self.request, {'MESSAGE_ID': 'auction_complaint_patch'})) return {'data': self.context.serialize("view")}
def patch_auction_document(self): if hasattr(self, 'dgf_platform_legal_details_from' ) and get_now() > self.dgf_platform_legal_details_from: response = self.app.get('/auctions/{}/documents'.format( self.auction_id)) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual( u'Місце та форма прийому заяв на участь в аукціоні та банківські реквізити для зарахування гарантійних внесків', # noqa response.json["data"][0]["title"]) self.assertEqual('x_dgfPlatformLegalDetails', response.json["data"][0]["documentType"]) doc_id = response.json["data"][0]['id'] response = self.app.patch_json('/auctions/{}/documents/{}'.format( self.auction_id, doc_id), { "data": { 'format': 'application/msword', "documentType": 'auctionNotice' } }, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [{ u'description': [ u'First document should be document with x_dgfPlatformLegalDetails documentType' ], u'location': u'body', u'name': u'documents' }]) response = self.app.post( '/auctions/{}/documents?acc_token={}'.format(self.auction_id, self.auction_token), upload_files=[('file', str(Header(u'укр.doc', 'utf-8')), 'content')]) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] # dateModified = response.json["data"]['dateModified'] self.assertIn(doc_id, response.headers['Location']) self.assertEqual(u'укр.doc', response.json["data"]["title"]) self.assertNotIn("documentType", response.json["data"]) response = self.app.patch_json( '/auctions/{}/documents/{}?acc_token={}'.format( self.auction_id, doc_id, self.auction_token), {"data": { "documentOf": "lot" }}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ { u'description': [u'This field is required.'], u'location': u'body', u'name': u'relatedItem' }, ]) response = self.app.patch_json( '/auctions/{}/documents/{}?acc_token={}'.format( self.auction_id, doc_id, self.auction_token), {"data": { "documentOf": "lot", "relatedItem": '0' * 32 }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']['relatedItem'], '0' * 32) self.assertEqual(response.json['data']['documentOf'], 'lot') response = self.app.patch_json( '/auctions/{}/documents/{}?acc_token={}'.format( self.auction_id, doc_id, self.auction_token), {"data": { "documentOf": "item", "relatedItem": '0' * 32 }}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual( response.json['errors'], [{ u'description': [u'relatedItem should be one of items'], u'location': u'body', u'name': u'relatedItem' }]) response = self.app.patch_json( '/auctions/{}/documents/{}?acc_token={}'.format( self.auction_id, doc_id, self.auction_token), { "data": { "description": "document description", "documentType": 'notice' } }) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(doc_id, response.json["data"]["id"]) self.assertIn("documentType", response.json["data"]) self.assertEqual(response.json["data"]["documentType"], 'notice') response = self.app.patch_json( '/auctions/{}/documents/{}?acc_token={}'.format( self.auction_id, doc_id, self.auction_token), {"data": { "documentType": None }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(doc_id, response.json["data"]["id"]) self.assertNotIn("documentType", response.json["data"]) response = self.app.get('/auctions/{}/documents/{}'.format( self.auction_id, doc_id)) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(doc_id, response.json["data"]["id"]) self.assertEqual('document description', response.json["data"]["description"]) # self.assertTrue(dateModified < response.json["data"]["dateModified"]) self.set_status('active.auction') response = self.app.patch_json( '/auctions/{}/documents/{}?acc_token={}'.format( self.auction_id, doc_id, self.auction_token), {"data": { "description": "document description" }}, status=403) self.assertEqual(response.status, '403 Forbidden') self.assertEqual(response.content_type, 'application/json') self.assertEqual( response.json['errors'][0]["description"], "Can't update document in current (active.auction) auction status")
def from1to2(registry): class Request(object): def __init__(self, registry): self.registry = registry results = registry.db.iterview('auctions/all', 2**10, include_docs=True) request = Request(registry) root = Root(request) docs = [] for i in results: auction = i.doc procurement_method_types = get_procurement_method_types( registry, ('tessel', )) if auction[ 'procurementMethodType'] not in procurement_method_types or auction[ 'status'] != 'active.awarded' or 'contracts' not in auction: continue changed = False contract = filter(lambda x: x['status'] == 'pending', auction['contracts'])[0] award = filter(lambda x: x['id'] == contract['awardID'], auction['awards'])[0] if not award['complaintPeriod'].get('endDate', False): award['complaintPeriod']['endDate'] = contract['date'] changed = True if not auction['awardPeriod'].get('endDate', False): auction['awardPeriod']['endDate'] = contract['date'] changed = True if not changed: continue auction_id = auction['_id'] model = registry.auction_procurementMethodTypes.get( auction['procurementMethodType']) if model: try: auction = model(auction) auction.__parent__ = root auction = auction.to_primitive() except: # pragma: no cover LOGGER.error( "Failed migration of auction {} to schema 2.".format( auction_id), extra={ 'MESSAGE_ID': 'migrate_data_failed', 'AUCTION_ID': auction_id }) else: LOGGER.info( "Auction {} migrated to schema 2.".format(auction_id), extra={ 'MESSAGE_ID': 'migrate_data', 'AUCTION_ID': auction_id }) auction['dateModified'] = get_now().isoformat() docs.append(auction) if len(docs) >= 2**7: # pragma: no cover registry.db.update(docs) docs = [] if docs: registry.db.update(docs)
from copy import deepcopy from uuid import uuid4 from datetime import timedelta from openprocurement.auctions.core.utils import (get_now) from openprocurement.auctions.geb.tests.fixtures.calculator import ( AwardCalculator as Calculator) from openprocurement.auctions.geb.tests.fixtures.common import ( test_organization) from openprocurement.auctions.geb.tests.fixtures.documents import ( AUCTION_PROTOCOL_DOCUMENT) from openprocurement.auctions.geb.utils import ( calculate_certainly_business_date as ccbd) verification_period_start = ccbd(get_now(), -timedelta(days=1), specific_hour=16) calculator = Calculator(verification_period_start, 'verificationPeriod', 'start') AWARD_PENDING = { "status": "pending", "verificationPeriod": { "startDate": calculator.verificationPeriod.startDate.isoformat(), "endDate": calculator.verificationPeriod.endDate.isoformat() }, "complaintPeriod": { "startDate": calculator.complaintPeriod.startDate.isoformat(), }, "suppliers": [test_organization], "signingPeriod": {
def patch(self): """Update of proposal Example request to change bid proposal: .. sourcecode:: http PATCH /auctions/4879d3f8ee2443169b5fbbc9f89fa607/bids/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json { "data": { "value": { "amount": 600 } } } And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "value": { "amount": 600, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ if self.request.authenticated_role != 'Administrator' and self.request.validated[ 'auction_status'] != 'active.tendering': self.request.errors.add( 'body', 'data', 'Can\'t update bid in current ({}) auction status'.format( self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if self.request.authenticated_role != 'Administrator' and ( auction.tenderPeriod.startDate and get_now() < auction.tenderPeriod.startDate or get_now() > auction.tenderPeriod.endDate): self.request.errors.add( 'body', 'data', 'Bid can be updated only during the tendering period: from ({}) to ({}).' .format( auction.tenderPeriod.startDate and auction.tenderPeriod.startDate.isoformat(), auction.tenderPeriod.endDate.isoformat())) self.request.errors.status = 403 return if self.request.authenticated_role != 'Administrator': bid_status_to = self.request.validated['data'].get("status") if bid_status_to != self.request.context.status and bid_status_to != "active": self.request.errors.add( 'body', 'bid', 'Can\'t update bid to ({}) status'.format(bid_status_to)) self.request.errors.status = 403 return value = self.request.validated['data'].get( "value") and self.request.validated['data']["value"].get("amount") if value and value != self.request.context.get("value", {}).get("amount"): self.request.validated['data']['date'] = get_now().isoformat() if self.request.context.lotValues: lotValues = dict([(i.relatedLot, i.value.amount) for i in self.request.context.lotValues]) for lotvalue in self.request.validated['data'].get( "lotValues", []): if lotvalue['relatedLot'] in lotValues and lotvalue.get( "value", {}).get("amount") != lotValues[lotvalue['relatedLot']]: lotvalue['date'] = get_now().isoformat() self.request.validated['auction'].modified = False if apply_patch(self.request, src=self.request.context.serialize()): self.LOGGER.info( 'Updated auction bid {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_patch'})) return {'data': self.request.context.serialize("view")}
def invalidate_bids_data(auction): for bid in auction.bids: setattr(bid, "status", "invalid") auction.rectificationPeriod.invalidationDate = get_now()
def collection_post(self): """Registration of new bid proposal Creating new Bid proposal ------------------------- Example request to create bid proposal: .. sourcecode:: http POST /auctions/4879d3f8ee2443169b5fbbc9f89fa607/bids HTTP/1.1 Host: example.com Accept: application/json { "data": { "tenderers": [ { "id": { "name": "Державне управління справами", "scheme": "https://ns.openprocurement.org/ua/edrpou", "uid": "00037256", "uri": "http://www.dus.gov.ua/" }, "address": { "countryName": "Україна", "postalCode": "01220", "region": "м. Київ", "locality": "м. Київ", "streetAddress": "вул. Банкова, 11, корпус 1" } } ], "value": { "amount": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } This is what one should expect in response: .. sourcecode:: http HTTP/1.1 201 Created Content-Type: application/json { "data": { "id": "4879d3f8ee2443169b5fbbc9f89fa607", "status": "registration", "date": "2014-10-28T11:44:17.947Z", "tenderers": [ { "id": { "name": "Державне управління справами", "scheme": "https://ns.openprocurement.org/ua/edrpou", "uid": "00037256", "uri": "http://www.dus.gov.ua/" }, "address": { "countryName": "Україна", "postalCode": "01220", "region": "м. Київ", "locality": "м. Київ", "streetAddress": "вул. Банкова, 11, корпус 1" } } ], "value": { "amount": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ # See https://github.com/open-contracting/standard/issues/78#issuecomment-59830415 # for more info upon schema auction = self.request.validated['auction'] if self.request.validated['auction_status'] != 'active.tendering': self.request.errors.add( 'body', 'data', 'Can\'t add bid in current ({}) auction status'.format( self.request.validated['auction_status'])) self.request.errors.status = 403 return if auction.tenderPeriod.startDate and get_now( ) < auction.tenderPeriod.startDate or get_now( ) > auction.tenderPeriod.endDate: self.request.errors.add( 'body', 'data', 'Bid can be added only during the tendering period: from ({}) to ({}).' .format( auction.tenderPeriod.startDate and auction.tenderPeriod.startDate.isoformat(), auction.tenderPeriod.endDate.isoformat())) self.request.errors.status = 403 return bid = self.request.validated['bid'] set_ownership(bid, self.request) auction.bids.append(bid) auction.modified = False if save_auction(self.request): self.LOGGER.info( 'Created auction bid {}'.format(bid.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_create'}, {'bid_id': bid.id})) self.request.response.status = 201 route = self.request.matched_route.name.replace("collection_", "") self.request.response.headers[ 'Location'] = self.request.current_route_url(_route_name=route, bid_id=bid.id, _query={}) return { 'data': bid.serialize('view'), 'access': { 'token': bid.owner_token } }
def check_status(request): auction = request.validated['auction'] now = get_now() for complaint in auction.complaints: check_complaint_status(request, complaint, now) for award in auction.awards: for complaint in award.complaints: check_complaint_status(request, complaint, now) if not auction.lots and auction.status == 'active.tendering' and auction.tenderPeriod.endDate <= now: LOGGER.info('Switched auction {} to {}'.format(auction['id'], 'active.auction'), extra=context_unpack( request, {'MESSAGE_ID': 'switched_auction_active.auction'})) auction.status = 'active.auction' remove_draft_bids(request) remove_invalid_bids(request) check_bids(request) return elif auction.lots and auction.status == 'active.tendering' and auction.tenderPeriod.endDate <= now: LOGGER.info('Switched auction {} to {}'.format(auction['id'], 'active.auction'), extra=context_unpack( request, {'MESSAGE_ID': 'switched_auction_active.auction'})) auction.status = 'active.auction' remove_draft_bids(request) remove_invalid_bids(request) check_bids(request) [ setattr(i.auctionPeriod, 'startDate', None) for i in auction.lots if i.numberOfBids < 2 and i.auctionPeriod ] return elif not auction.lots and auction.status == 'active.awarded': standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in auction.awards if a.complaintPeriod.endDate ] if not standStillEnds: return standStillEnd = max(standStillEnds) if standStillEnd <= now: check_auction_status(request) elif auction.lots and auction.status in [ 'active.qualification', 'active.awarded' ]: if any([ i['status'] in auction.block_complaint_status and i.relatedLot is None for i in auction.complaints ]): return for lot in auction.lots: if lot['status'] != 'active': continue lot_awards = [i for i in auction.awards if i.lotID == lot.id] standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in lot_awards if a.complaintPeriod.endDate ] if not standStillEnds: continue standStillEnd = max(standStillEnds) if standStillEnd <= now: check_auction_status(request) return
def validate_documents(self, data, docs): if (data.get('revisions')[0].date if data.get('revisions') else get_now()) > DGF_PLATFORM_LEGAL_DETAILS_FROM and \ (docs and docs[0].documentType != 'x_dgfPlatformLegalDetails' or any([i.documentType == 'x_dgfPlatformLegalDetails' for i in docs[1:]])): raise ValidationError( u"First document should be document with x_dgfPlatformLegalDetails documentType" )
def reset_auction_period(self): self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/auctions/{}'.format(self.auction_id), {'data': { 'id': self.auction_id }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['data']["status"], 'active.tendering') if self.initial_lots: item = response.json['data']["lots"][0] else: item = response.json['data'] self.assertIn('auctionPeriod', item) self.assertIn('shouldStartAfter', item['auctionPeriod']) self.assertGreaterEqual(response.json['data']['tenderPeriod']['endDate'], item['auctionPeriod']['shouldStartAfter']) self.assertEqual(response.json['data']['next_check'], response.json['data']['enquiryPeriod']['endDate']) self.app.authorization = ('Basic', ('auction', '')) if self.initial_lots: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), { 'data': { "lots": [{ "auctionPeriod": { "startDate": "9999-01-01T00:00:00" } }] } }) item = response.json['data']["lots"][0] else: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), {'data': { "auctionPeriod": { "startDate": "9999-01-01T00:00:00" } }}) item = response.json['data'] self.assertEqual(response.status, '200 OK') self.assertGreaterEqual(response.json['data']['tenderPeriod']['endDate'], item['auctionPeriod']['shouldStartAfter']) self.assertIn('9999-01-01T00:00:00', item['auctionPeriod']['startDate']) self.set_status('active.auction', {'status': 'active.tendering'}) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/auctions/{}'.format(self.auction_id), {'data': { 'id': self.auction_id }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']["status"], 'active.auction') item = response.json['data']["lots"][ 0] if self.initial_lots else response.json['data'] self.assertGreaterEqual(item['auctionPeriod']['shouldStartAfter'], response.json['data']['enquiryPeriod']['endDate']) self.app.authorization = ('Basic', ('auction', '')) if self.initial_lots: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), { 'data': { "lots": [{ "auctionPeriod": { "startDate": "9999-01-01T00:00:00" } }] } }) item = response.json['data']["lots"][0] else: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), {'data': { "auctionPeriod": { "startDate": "9999-01-01T00:00:00" } }}) item = response.json['data'] self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']["status"], 'active.auction') self.assertGreaterEqual(item['auctionPeriod']['shouldStartAfter'], response.json['data']['enquiryPeriod']['endDate']) self.assertIn('9999-01-01T00:00:00', item['auctionPeriod']['startDate']) self.assertIn('9999-01-01T00:00:00', response.json['data']['next_check']) now = get_now().isoformat() auction = self.db.get(self.auction_id) if self.initial_lots: auction['lots'][0]['auctionPeriod']['startDate'] = now else: auction['auctionPeriod']['startDate'] = now self.db.save(auction) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/auctions/{}'.format(self.auction_id), {'data': { 'id': self.auction_id }}) self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']["status"], 'active.auction') item = response.json['data']["lots"][ 0] if self.initial_lots else response.json['data'] self.assertGreaterEqual(item['auctionPeriod']['shouldStartAfter'], response.json['data']['enquiryPeriod']['endDate']) self.assertGreater(response.json['data']['next_check'], item['auctionPeriod']['startDate']) self.assertEqual(response.json['data']['next_check'], self.db.get(self.auction_id)['next_check']) self.app.authorization = ('Basic', ('auction', '')) if self.initial_lots: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), { 'data': { "lots": [{ "auctionPeriod": { "startDate": response.json['data']['tenderPeriod']['endDate'] } }] } }) item = response.json['data']["lots"][0] else: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), { 'data': { "auctionPeriod": { "startDate": response.json['data']['enquiryPeriod']['endDate'] } } }) item = response.json['data'] self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']["status"], 'active.auction') self.assertNotIn('9999-01-01T00:00:00', item['auctionPeriod']['startDate']) self.assertGreater(response.json['data']['next_check'], response.json['data']['enquiryPeriod']['endDate']) auction = self.db.get(self.auction_id) self.assertGreater(auction['next_check'], response.json['data']['enquiryPeriod']['endDate']) auction['enquiryPeriod']['endDate'] = auction['enquiryPeriod']['startDate'] if self.initial_lots: auction['lots'][0]['auctionPeriod']['startDate'] = auction[ 'enquiryPeriod']['startDate'] else: auction['auctionPeriod']['startDate'] = auction['enquiryPeriod'][ 'startDate'] self.db.save(auction) self.app.authorization = ('Basic', ('chronograph', '')) response = self.app.patch_json('/auctions/{}'.format(self.auction_id), {'data': { 'id': self.auction_id }}) if self.initial_lots: item = response.json['data']["lots"][0] else: item = response.json['data'] self.assertGreaterEqual(item['auctionPeriod']['shouldStartAfter'], response.json['data']['enquiryPeriod']['endDate']) self.assertNotIn('next_check', response.json['data']) self.assertNotIn('next_check', self.db.get(self.auction_id)) shouldStartAfter = item['auctionPeriod']['shouldStartAfter'] response = self.app.patch_json('/auctions/{}'.format(self.auction_id), {'data': { 'id': self.auction_id }}) if self.initial_lots: item = response.json['data']["lots"][0] else: item = response.json['data'] self.assertEqual(item['auctionPeriod']['shouldStartAfter'], shouldStartAfter) self.assertNotIn('next_check', response.json['data']) self.app.authorization = ('Basic', ('auction', '')) if self.initial_lots: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), { 'data': { "lots": [{ "auctionPeriod": { "startDate": "9999-01-01T00:00:00" } }] } }) item = response.json['data']["lots"][0] else: response = self.app.patch_json( '/auctions/{}'.format(self.auction_id), {'data': { "auctionPeriod": { "startDate": "9999-01-01T00:00:00" } }}) item = response.json['data'] self.assertEqual(response.status, '200 OK') self.assertEqual(response.json['data']["status"], 'active.auction') self.assertGreaterEqual(item['auctionPeriod']['shouldStartAfter'], response.json['data']['enquiryPeriod']['endDate']) self.assertIn('9999-01-01T00:00:00', item['auctionPeriod']['startDate']) self.assertIn('9999-01-01T00:00:00', response.json['data']['next_check'])
def __init__(self, request, context): self._now = get_now() self._request = request self._context = context
def setUp(self): self.initial_data['value']['amount'] = 479.0 / 2 super(InsiderAuctionContractResourceTest, self).setUp() # Create award authorization = self.app.authorization self.app.authorization = ('Basic', ('auction', '')) response = self.app.get('/auctions/{}'.format(self.auction_id)) self.assertEqual(response.status, '200 OK') auction = response.json['data'] value_threshold = auction['value']['amount'] + auction['minimalStep'][ 'amount'] now = get_now() auction_result = { 'bids': [{ "id": b['id'], "date": (now - timedelta(seconds=i)).isoformat(), "value": { "amount": value_threshold * 2 }, } for i, b in enumerate(self.initial_bids)] } response = self.app.post_json( '/auctions/{}/auction'.format(self.auction_id), {'data': auction_result}) self.assertEqual(response.status, '200 OK') auction = response.json['data'] self.app.authorization = authorization self.award = auction['awards'][0] self.award_id = self.award['id'] self.award_value = self.award['value'] self.award_suppliers = self.award['suppliers'] self.set_status('active.qualification') self.app.authorization = ('Basic', ('token', '')) response = self.app.post( '/auctions/{}/awards/{}/documents?acc_token={}'.format( self.auction_id, self.award_id, self.auction_token), upload_files=[('file', 'auction_protocol.pdf', 'content')]) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] response = self.app.patch_json( '/auctions/{}/awards/{}/documents/{}?acc_token={}'.format( self.auction_id, self.award_id, doc_id, self.auction_token), { "data": { "description": "auction protocol", "documentType": 'auctionProtocol' } }) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json["data"]["documentType"], 'auctionProtocol') self.assertEqual(response.json["data"]["author"], 'auction_owner') self.app.patch_json( '/auctions/{}/awards/{}'.format(self.auction_id, self.award_id), {"data": { "status": "active" }}) response = self.app.get('/auctions/{}'.format(self.auction_id)) auction = response.json['data'] self.award_contract_id = auction['contracts'][0]['id']
def next_check(self): if self.suspended: return None now = get_now() checks = [] if self.status == 'active.tendering' and self.enquiryPeriod and self.enquiryPeriod.endDate: checks.append(self.enquiryPeriod.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: checks.append(self.auctionPeriod.startDate.astimezone(TZ)) elif now < calc_auction_end_time( NUMBER_OF_STAGES, self.auctionPeriod.startDate).astimezone(TZ): checks.append( calc_auction_end_time( NUMBER_OF_STAGES, self.auctionPeriod.startDate).astimezone(TZ)) elif not self.lots and self.status == 'active.qualification': for award in self.awards: if award.status == 'pending': checks.append( award.verificationPeriod.endDate.astimezone(TZ)) elif not self.lots and self.status == 'active.awarded' and not any( [i.status in self.block_complaint_status for i in self.complaints]) and not any([ i.status in self.block_complaint_status for a in self.awards for i in a.complaints ]): standStillEnds = [ a.complaintPeriod.endDate.astimezone(TZ) for a in self.awards if a.complaintPeriod.endDate ] for award in self.awards: if award.status == 'active': checks.append(award.signingPeriod.endDate.astimezone(TZ)) last_award_status = self.awards[-1].status if self.awards else '' if standStillEnds and last_award_status == 'unsuccessful': checks.append(max(standStillEnds)) if self.status.startswith('active'): from openprocurement.auctions.core.utils import calculate_business_date for complaint in self.complaints: if complaint.status == 'claim' and complaint.dateSubmitted: checks.append( calculate_business_date( complaint.dateSubmitted, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) elif complaint.status == 'answered' and complaint.dateAnswered: checks.append( calculate_business_date( complaint.dateAnswered, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) for award in self.awards: for complaint in award.complaints: if complaint.status == 'claim' and complaint.dateSubmitted: checks.append( calculate_business_date( complaint.dateSubmitted, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) elif complaint.status == 'answered' and complaint.dateAnswered: checks.append( calculate_business_date( complaint.dateAnswered, AUCTIONS_COMPLAINT_STAND_STILL_TIME, self)) return min(checks).isoformat() if checks else None
def setUp(self): super(AuctionContractDocumentResourceTest, self).setUp() # Create award authorization = self.app.authorization self.app.authorization = ('Basic', ('auction', '')) now = get_now() auction_result = { 'bids': [{ "id": b['id'], "date": (now - timedelta(seconds=i)).isoformat(), "value": b['value'] } for i, b in enumerate(self.initial_bids)] } response = self.app.post_json( '/auctions/{}/auction'.format(self.auction_id), {'data': auction_result}) self.assertEqual(response.status, '200 OK') auction = response.json['data'] self.app.authorization = authorization self.award = auction['awards'][0] self.award_id = self.award['id'] self.award_value = self.award['value'] self.award_suppliers = self.award['suppliers'] response = self.app.post( '/auctions/{}/awards/{}/documents?acc_token={}'.format( self.auction_id, self.award_id, self.auction_token), upload_files=[('file', 'auction_protocol.pdf', 'content')]) self.assertEqual(response.status, '201 Created') self.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] response = self.app.patch_json( '/auctions/{}/awards/{}/documents/{}?acc_token={}'.format( self.auction_id, self.award_id, doc_id, self.auction_token), { "data": { "description": "auction protocol", "documentType": 'auctionProtocol' } }) self.assertEqual(response.status, '200 OK') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json["data"]["documentType"], 'auctionProtocol') self.assertEqual(response.json["data"]["author"], 'auction_owner') self.app.patch_json( '/auctions/{}/awards/{}?acc_token={}'.format( self.auction_id, self.award_id, self.auction_token), {"data": { "status": "pending.payment" }}) self.app.patch_json( '/auctions/{}/awards/{}?acc_token={}'.format( self.auction_id, self.award_id, self.auction_token), {"data": { "status": "active" }}) # Assure contract for award is created response = self.app.get('/auctions/{}/contracts'.format( self.auction_id)) contract = response.json['data'][0] self.contract_id = contract['id']
def rounding_shouldStartAfter(start_after, auction, use_from=datetime(2016, 6, 1, tzinfo=TZ)): if (auction.enquiryPeriod and auction.enquiryPeriod.startDate or get_now()) > use_from and not (SANDBOX_MODE and auction.submissionMethodDetails and u'quick' in auction.submissionMethodDetails): midnigth = datetime.combine(start_after.date(), time(0, tzinfo=start_after.tzinfo)) if start_after >= midnigth: start_after = midnigth + timedelta(1) return start_after
def delete(self): """Cancelling the proposal Example request for cancelling the proposal: .. sourcecode:: http DELETE /auctions/4879d3f8ee2443169b5fbbc9f89fa607/bids/71b6c23ed8944d688e92a31ec8c3f61a HTTP/1.1 Host: example.com Accept: application/json And here is the response to be expected: .. sourcecode:: http HTTP/1.0 200 OK Content-Type: application/json { "data": { "value": { "amount": 489, "currency": "UAH", "valueAddedTaxIncluded": true } } } """ # Delete bid permission where deny for everyone # For return possibility delete bid remove this function bid = self.request.context if self.request.validated['auction_status'] != 'active.tendering': self.request.errors.add( 'body', 'data', 'Can\'t delete bid in current ({}) auction status'.format( self.request.validated['auction_status'])) self.request.errors.status = 403 return auction = self.request.validated['auction'] if auction.tenderPeriod.startDate and get_now( ) < auction.tenderPeriod.startDate or get_now( ) > auction.tenderPeriod.endDate: self.request.errors.add( 'body', 'data', 'Bid can be deleted only during the tendering period: from ({}) to ({}).' .format( auction.tenderPeriod.startDate and auction.tenderPeriod.startDate.isoformat(), auction.tenderPeriod.endDate.isoformat())) self.request.errors.status = 403 return res = bid.serialize("view") self.request.validated['auction'].bids.remove(bid) self.request.validated['auction'].modified = False if save_auction(self.request): self.LOGGER.info( 'Deleted auction bid {}'.format(self.request.context.id), extra=context_unpack(self.request, {'MESSAGE_ID': 'auction_bid_delete'})) return {'data': res}
def create_award(test_case): # Create award authorization = test_case.app.authorization test_case.app.authorization = ('Basic', ('auction', '')) now = get_now() auction_result = { 'bids': [{ "id": b['id'], "date": (now - timedelta(seconds=i)).isoformat(), "value": b['value'] } for i, b in enumerate(test_case.initial_bids)] } response = test_case.app.post_json( '/auctions/{}/auction'.format(test_case.auction_id), {'data': auction_result}) test_case.assertEqual(response.status, '200 OK') auction = response.json['data'] test_case.app.authorization = authorization test_case.award = auction['awards'][0] test_case.award_id = test_case.award['id'] test_case.award_value = test_case.award['value'] test_case.award_suppliers = test_case.award['suppliers'] test_case.set_status('active.qualification') test_case.app.authorization = ('Basic', ('token', '')) response = test_case.app.post( '/auctions/{}/awards/{}/documents?acc_token={}'.format( test_case.auction_id, test_case.award_id, test_case.auction_token), upload_files=[('file', 'auction_protocol.pdf', 'content')]) test_case.assertEqual(response.status, '201 Created') test_case.assertEqual(response.content_type, 'application/json') doc_id = response.json["data"]['id'] response = test_case.app.patch_json( '/auctions/{}/awards/{}/documents/{}?acc_token={}'.format( test_case.auction_id, test_case.award_id, doc_id, test_case.auction_token), { "data": { "description": "auction protocol", "documentType": 'auctionProtocol' } }) test_case.assertEqual(response.status, '200 OK') test_case.assertEqual(response.content_type, 'application/json') test_case.assertEqual(response.json["data"]["documentType"], 'auctionProtocol') test_case.assertEqual(response.json["data"]["author"], 'auction_owner') test_case.app.patch_json( '/auctions/{}/awards/{}'.format(test_case.auction_id, test_case.award_id), {"data": { "status": "pending" }}) test_case.app.patch_json( '/auctions/{}/awards/{}'.format(test_case.auction_id, test_case.award_id), {"data": { "status": "active" }}) get_auction_response = test_case.app.get('/auctions/{}'.format( test_case.auction_id, )) test_case.award_contract_id = get_auction_response.\ json['data']['contracts'][0]['id']
def create_auction_invalid(self): request_path = '/auctions' response = self.app.post(request_path, 'data', status=415) self.assertEqual(response.status, '415 Unsupported Media Type') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': u"Content-Type header should be one of ['application/json']", u'location': u'header', u'name': u'Content-Type'} ]) response = self.app.post( request_path, 'data', content_type='application/json', status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ JSON_RENDERER_ERROR ]) response = self.app.post_json(request_path, 'data', status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': u'Data not available', u'location': u'body', u'name': u'data'} ]) response = self.app.post_json(request_path, {'not_data': {}}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': u'Data not available', u'location': u'body', u'name': u'data'} ]) response = self.app.post_json(request_path, {'data': []}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': u'Data not available', u'location': u'body', u'name': u'data'} ]) response = self.app.post_json(request_path, {'data': {'procurementMethodType': 'invalid_value'}}, status=415) self.assertEqual(response.status, '415 Unsupported Media Type') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': u'procurementMethodType is not implemented', u'location': u'body', u'name': u'data'} ]) response = self.app.post_json(request_path, {'data': {'invalid_field': 'invalid_value', 'procurementMethodType': self.initial_data['procurementMethodType']}}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': u'Rogue field', u'location': u'body', u'name': u'invalid_field'} ]) response = self.app.post_json(request_path, {'data': {'value': 'invalid_value', 'procurementMethodType': self.initial_data['procurementMethodType']}}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': [ u'Please use a mapping for this field or Value instance instead of unicode.'], u'location': u'body', u'name': u'value'} ]) response = self.app.post_json(request_path, {'data': {'procurementMethod': 'invalid_value', 'procurementMethodType': self.initial_data['procurementMethodType']}}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertIn({u'description': [u"Value must be one of ['open', 'selective', 'limited']."], u'location': u'body', u'name': u'procurementMethod'}, response.json['errors']) #self.assertIn({u'description': [u'This field is required.'], u'location': u'body', u'name': u'tenderPeriod'}, response.json['errors']) # self.assertIn({u'description': [u'This field is required.'], u'location': u'body', u'name': u'minimalStep'}, response.json['errors']) #self.assertIn({u'description': [u'This field is required.'], u'location': u'body', u'name': u'enquiryPeriod'}, response.json['errors']) self.assertIn({u'description': [u'This field is required.'], u'location': u'body', u'name': u'value'}, response.json['errors']) response = self.app.post_json(request_path, {'data': {'enquiryPeriod': {'endDate': 'invalid_value'}, 'procurementMethodType': self.initial_data['procurementMethodType']}}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': {u'endDate': [u"Could not parse invalid_value. Should be ISO8601."]}, u'location': u'body', u'name': u'enquiryPeriod'} ]) response = self.app.post_json(request_path, {'data': {'enquiryPeriod': {'endDate': '9999-12-31T23:59:59.999999'}, 'procurementMethodType': self.initial_data['procurementMethodType']}}, status=422) self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': {u'endDate': [u'date value out of range']}, u'location': u'body', u'name': u'enquiryPeriod'} ]) self.initial_data['tenderPeriod'] = self.initial_data.pop('auctionPeriod') response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) self.initial_data['auctionPeriod'] = self.initial_data.pop('tenderPeriod') self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': {u'startDate': [u'This field is required.']}, u'location': u'body', u'name': u'auctionPeriod'} ]) self.initial_data['tenderPeriod'] = {'startDate': '2014-10-31T00:00:00', 'endDate': '2014-10-01T00:00:00'} response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) self.initial_data.pop('tenderPeriod') self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': {u'startDate': [u'period should begin before its end']}, u'location': u'body', u'name': u'tenderPeriod'} ]) #data = self.initial_data['tenderPeriod'] #self.initial_data['tenderPeriod'] = {'startDate': '2014-10-31T00:00:00', 'endDate': '2015-10-01T00:00:00'} #response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) #self.initial_data['tenderPeriod'] = data #self.assertEqual(response.status, '422 Unprocessable Entity') #self.assertEqual(response.content_type, 'application/json') #self.assertEqual(response.json['status'], 'error') #self.assertEqual(response.json['errors'], [ #{u'description': [u'period should begin after enquiryPeriod'], u'location': u'body', u'name': u'tenderPeriod'} #]) now = get_now() #self.initial_data['awardPeriod'] = {'startDate': now.isoformat(), 'endDate': now.isoformat()} #response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) #del self.initial_data['awardPeriod'] #self.assertEqual(response.status, '422 Unprocessable Entity') #self.assertEqual(response.content_type, 'application/json') #self.assertEqual(response.json['status'], 'error') #self.assertEqual(response.json['errors'], [ #{u'description': [u'period should begin after tenderPeriod'], u'location': u'body', u'name': u'awardPeriod'} #]) data = self.initial_data['auctionPeriod'] self.initial_data['auctionPeriod'] = {'startDate': (now + timedelta(days=15)).isoformat(), 'endDate': (now + timedelta(days=15)).isoformat()} self.initial_data['awardPeriod'] = {'startDate': (now + timedelta(days=14)).isoformat(), 'endDate': (now + timedelta(days=14)).isoformat()} response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) self.initial_data['auctionPeriod'] = data del self.initial_data['awardPeriod'] self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': [u'period should begin after auctionPeriod'], u'location': u'body', u'name': u'awardPeriod'} ]) # # data = self.initial_data['minimalStep'] # self.initial_data['minimalStep'] = {'amount': '1000.0'} # response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) # self.initial_data['minimalStep'] = data # self.assertEqual(response.status, '422 Unprocessable Entity') # self.assertEqual(response.content_type, 'application/json') # self.assertEqual(response.json['status'], 'error') # self.assertEqual(response.json['errors'], [ # {u'description': [u'value should be less than value of auction'], u'location': u'body', u'name': u'minimalStep'} # ]) # # data = self.initial_data['minimalStep'] # self.initial_data['minimalStep'] = {'amount': '100.0', 'valueAddedTaxIncluded': False} # response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) # self.initial_data['minimalStep'] = data # self.assertEqual(response.status, '422 Unprocessable Entity') # self.assertEqual(response.content_type, 'application/json') # self.assertEqual(response.json['status'], 'error') # self.assertEqual(response.json['errors'], [ # {u'description': [u'valueAddedTaxIncluded should be identical to valueAddedTaxIncluded of value of auction'], u'location': u'body', u'name': u'minimalStep'} # ]) # # data = self.initial_data['minimalStep'] # self.initial_data['minimalStep'] = {'amount': '100.0', 'currency': "USD"} # response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) # self.initial_data['minimalStep'] = data # self.assertEqual(response.status, '422 Unprocessable Entity') # self.assertEqual(response.content_type, 'application/json') # self.assertEqual(response.json['status'], 'error') # self.assertEqual(response.json['errors'], [ # {u'description': [u'currency should be identical to currency of value of auction'], u'location': u'body', u'name': u'minimalStep'} # ]) # # auction_data = deepcopy(self.initial_data) # auction_data['value'] = {'amount': '100.0', 'currency': "USD"} # auction_data['minimalStep'] = {'amount': '5.0', 'currency': "USD"} # response = self.app.post_json(request_path, {'data': auction_data}, status=422) # self.assertEqual(response.status, '422 Unprocessable Entity') # self.assertEqual(response.content_type, 'application/json') # self.assertEqual(response.json['status'], 'error') # self.assertEqual(response.json['errors'], [ # {u'description': [u'currency should be only UAH'], u'location': u'body', u'name': u'value'} # ]) data = self.initial_data["procuringEntity"]["contactPoint"]["telephone"] del self.initial_data["procuringEntity"]["contactPoint"]["telephone"] response = self.app.post_json(request_path, {'data': self.initial_data}, status=422) self.initial_data["procuringEntity"]["contactPoint"]["telephone"] = data self.assertEqual(response.status, '422 Unprocessable Entity') self.assertEqual(response.content_type, 'application/json') self.assertEqual(response.json['status'], 'error') self.assertEqual(response.json['errors'], [ {u'description': {u'contactPoint': {u'email': [u'telephone or email should be present']}}, u'location': u'body', u'name': u'procuringEntity'} ])