Example #1
0
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()
}
Example #4
0
# -*- 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
Example #8
0
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")}
Example #11
0
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": {
Example #14
0
    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()
Example #16
0
    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"
         )
Example #19
0
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'])
Example #20
0
 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']
Example #22
0
    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
Example #23
0
    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']
Example #24
0
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
Example #25
0
    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}
Example #26
0
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']
Example #27
0
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'}
    ])